0

다음 작업을 수행하려고합니다.NSFetchedResultsController 및 백그라운드 컨텍스트가있는 UIManagedDocument

테이블 뷰에서 API에서 가져온 데이터를 표시하는 테이블 뷰가 있습니다. 이를 위해 나는 NSFetchedResultsController를 사용하고 있습니다 :

self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request 
                     managedObjectContext:self.database.managedObjectContext 
                     sectionNameKeyPath:nil 
                       cacheName:nil]; 

이 같은 배경의 맥락에서 내 실체를 만들 : 지금

NSManagedObjectContext *backgroundContext; 
    backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
    backgroundContext.parentContext = document.managedObjectContext; 

    [backgroundContext performBlock:^{ 
     [MyAPI createEntitiesInContext:backgroundContext]; 

     NSError *error = nil; 
     [backgroundContext save:&error]; 
     if (error) NSLog(@"error: %@",error.localizedDescription); 

     [document.managedObjectContext performBlock:^{ 
      [document updateChangeCount:UIDocumentChangeDone]; 
      [document.managedObjectContext save:nil]; 
     }]; 

내가 새로운 데이터를 얻을 수 (및 삽입 할 때마다/업데이트 실체를 바로 표시처럼 위), 내 NSFetchedResultsController 꽤 작동하지 않습니다해야합니다. 특히, 나는 항상 하나의 엔티티 (새로운 엔트리를 생성하지 않음)를 업데이트하지만, 내 테이블 뷰는 두 엔티티를 보여줍니다. 앱을 다시 시작하면 올바르게 표시됩니다.

self.database.managedObjectContext에서 엔티티 ([MyAPI createEntities])를 생성하면 모든 것이 잘 동작합니다.

내가 뭘 잘못하고 있는지 알기! 여기에있는 기존 스레드를 살펴보면 내가 올바른 방법으로하고 있다고 생각하게 만듭니다. 다시 말하지만, 핵심 데이터가 백그라운드 컨텍스트 (하지만 document.managedObjectContext)에 저장되지 않으면 잘 작동합니다 ...

답변

1

오늘 Apple 개발자 포럼에서 비슷한 문제에 관해 읽었습니다. 아마도 이것은 당신과 같은 문제인 https://devforums.apple.com/message/666492#666492입니다.이 경우 아마도 버그가있을 것입니다 (또는 적어도 다른 사람이 같은 문제를 논의하고 있습니다!).

가정하지 않는 한 중첩 된 컨텍스트에서 완벽하게 가능해야하므로 UIManagedDocument의 버그가없는 것으로 가정합니다.

나의 유일한 예약은 UIManagedDocument으로 작업하는 일괄로드를 얻으려고했는데 중첩 된 컨텍스트 (https://stackoverflow.com/q/11274412/1347502)와는 작동하지 않는 것 같습니다. NSFetchedResultsController의 주요 이점 중 하나는 배치 로딩을 통해 성능을 향상시킬 수 있다는 것입니다. 따라서 이것이 UIManagedDocument에서 수행 될 수 없다면 NSFetchedResultsControllerUIManagedDocument과 함께 사용할 준비가되지 않았지만 아직 그 문제의 최하점에 도달하지 못했습니다.

그 예약 외에, 중첩 된 컨텍스트와 배경 작업에 대해 읽거나 본 대부분의 지침은 피어 자식 컨텍스트로 수행되는 것으로 보입니다. 당신이 묘사 한 것은 부모, 자식, 손자 구성입니다. WWDC 2012 비디오에서 - 예를 들어

backgroundContext.parentContext = document.managedObjectContext.parentContext; 

애플은이 시나리오의 부모 컨텍스트 또 다른 피어 컨텍스트를 추가하는 것이 좋습니다 "세션 (214 개) 코어 데이터 모범 사례"(+ 16시 분), 작업이 비동기 적으로 수행 컨텍스트에 저장 한 다음 부모 호출로 백그라운드 컨텍스트에 저장합니다. 그런 다음 부모는 비동기 적으로 저장되고 피어 컨텍스트 (이 경우 document.managedObjectContext)는 가져 오기, 병합 또는 새로 고침을 통해 변경 내용에 액세스합니다. 이 또한 UIManagedDocument 문서에 설명되어 있습니다 :

  • 해당하는 경우, 당신은 부모 컨텍스트에 백그라운드 스레드에서 직접 데이터를로드 할 수 있습니다. parentContext를 사용하여 부모 컨텍스트를 가져올 수 있습니다. 부모 컨텍스트에 데이터를로드하면 자식 컨텍스트의 작업을 방해하지 않는다는 것을 의미합니다. 가져 오기를 실행하여 백그라운드에서로드 된 데이터 을 검색 할 수 있습니다.

[편집 :. 그냥 제프리의 제안 즉, 전혀 새로운 컨텍스트를 생성하고 바로 부모 컨텍스트를 사용하지 추천 할 수있는이를 다시 읽기]

이 문서는 제안 상기되고 그건 일반적으로 자식 컨텍스트에서는 저장을 호출하지 않고 UIManagedDocument의 저장 메서드를 사용합니다. 이것은 전화를 할 때 또는 문제의 일부일 수 있습니다. Jeffery가 언급 한 것처럼 상위 컨텍스트에서 save를 호출하는 것이 더 이상 권장되지 않습니다. 스택 오버플로에서 읽은 다른 대답은 UIManagedDocument을 저장하기 위해 updateChangeCount 만 사용하는 것이 좋습니다. 그러나 나는 애플로부터 어떤 것도 읽지 않았기 때문에 아마도이 경우 UIManagedDocument saveToURL:forSaveOperation:completionHandler: 메서드를 호출하면 모든 것을 동기화하고 저장하는 것이 적절할 것이다.

다음 명백한 문제는 NSFetchedResultsController에 변경이 발생했음을 알리는 것입니다. 위에서 설명한대로 설정을 간소화하고 다양한 NSManagedObjectContextObjectsDidChangeNotification에 가입하거나 다른 컨텍스트의 알림을 저장하고 UIMangedDocument이 저장되거나 자동 저장되거나 부모에 배경 변경 사항이 저장 될 때 호출되는 호출기가 있는지 확인해야합니다. 이 경우에 허용된다고 가정). NSFetchedResultsController이 기본 데이터와의 동기화를 유지하기 위해 이러한 알림에 연결되어 있다고 가정합니다.

또는 주체 컨텍스트에서 수동으로 가져 오기, 병합 또는 새로 고침을 수행하여 변경 사항을 가져온 다음 NSFetchedResultsController에 새로 고침해야한다고 알리는 것이 좋습니다.

개인적으로 나는 UIManagedDocument이 일반적인 소비를위한 준비가되었는지 궁금합니다. 올해 WWDC에 언급이 없었고, 훨씬 복잡한 해결책을 만드는 방법에 대한 오랜 토론이있었습니다. "세션 227 - iCloud 사용 코어 데이터 "나는 서버에서 데이터를 가져 내 방법에서

0

다른 컨텍스트에서 결과를 업데이트하기 때문에 다음과 같은 작업을 수행해야합니다. 보기 컨트롤러 -viewWillAppear: 메서드에서 [self.fetchedResultsController performFetch:&error]으로 전화하십시오.


는 업데이트

확인 후 [backgroundContext save:&error] 또는 [document.managedObjectContext save:nil]를 호출해서는 안됩니다. 참조 : UIManagedDocument Class Reference

일반적으로 표준 UIDocument 메서드를 사용하여 문서를 저장해야합니다. 하위 컨텍스트를 직접 저장하면 문서 컨텍스트가 아닌 상위 컨텍스트에 대한 변경 내용 만 커밋합니다. 상위 컨텍스트를 직접 저장하면 문서가 수행하는 다른 중요한 작업이 회피됩니다.

컨텍스트에서 생성 된 새 개체를 유지하려면 -insertedObjectsobtainPermanentIDsForObjects:error:을 사용해야했습니다.

다음으로 배경에서 실행할 새 컨텍스트를 만들 필요가 없다고 생각합니다. document.managedObjectContext.parentContext은 업데이트를 실행할 수있는 배경 컨텍스트 여야합니다.

마지막으로 [document updateChangeCount:UIDocumentChangeDone]을 자주 호출하지 않습니다. 이것은 문서에 의해 자동으로 처리됩니다. 언제든지 원하는대로 할 수 있지만 필수는 아닙니다.

다음은 내가 귀하의 -createEntitiesInContext 방법이라고 부릅니다.

[document.managedObjectContext.parentContext performBlock:^{ 
    [MyAPI createEntitiesInContext:document.managedObjectContext.parentContext]; 

    NSSet *objects = [document.managedObjectContext.parentContext insertedObjects]; 
    if (objects.count > 0) { 
     NSError *error = nil; 
     [document.managedObjectContext.parentContext obtainPermanentIDsForObjects:objects error:&error] 
     if (error) NSLog(@"error: %@",error.localizedDescription); 
    } 
}]; 
+0

흠을, 나는 생각 서로 다른 컨텍스트의 변경 사항이 병합되므로 fetchedResultsController가 결국 알림을 받게됩니다. 어쨌든 backgroundContext를 저장 한 후에도 [self.fetchedResultsController performFetch : nil]을 호출 해 보았습니다.하지만 여전히 동일한 상황이 있습니다. 내 테이블 뷰는 두 개의 엔티티를 표시합니다. 응용 프로그램을 다시 시작한 후 제대로 작동합니다. – user1013725

+0

또한 UIDocument가 있다는 것을 기억하십시오. 기본적으로 백그라운드 스레드에서 새 엔티티를 내 문서에 저장/업데이트하려고합니다. UIDocument의 managedObjectContext에 저장을 수행하면 UI가 뒤처집니다. 그래서 backgroundContext를 사용하여 작업을 시도했지만 어떻게 든 엉망이되거나 병합되지 않습니다. 나는 이제 꽤 절박 해지고있다. – user1013725

+0

아쉽게도 코드가 여전히 작동하지 않습니다. 그것은 나에게 완전히 이상하고 예측할 수없는 결과를 준다. 어떤 상황에서 배경 컨텍스트를 사용한 다음 저장을 호출하고 해당 배경 컨텍스트에 대한 영구 ID를 얻는 것이 었습니다. 그러나 두 번 다른 컨텍스트에서 엔터티를 만든 다음 병합하기 때문에 해당 업데이트 코드가 동시에 두 번 호출되면 경쟁 조건 문제가 발생합니다. 그것을 방지하는 방법을 모릅니다. – user1013725

1

으로, 내가 먼저 엔티티를 생성하고 그 후 나는이 문서에 대한 변경 사항 저장하려면 다음 두 가지 방법을 호출

[self.managedObjectContext performBlock:^{ 
    // create my entities 


    [self.document updateChangeCount:UIDocumentChangeDone]; 
    [self.document savePresentedItemChangesWithCompletionHandler:^(NSError *errorOrNil) { 
      ... 
     }]; 
}]; 
관련 문제