2017-11-19 36 views
0

나는 merge policies에 대해 읽었으며 변경 사항이 병합되는시기에 대해 서로 상충되는 아이디어를 제공합니다.iOS : 코어 데이터 병합 정책이 NSManagedObjectContext 저장 및 새로 고침 작업에 미치는 영향

백그라운드 대기열에 있고 주 대기열에 하나씩 두 개의 컨텍스트가 있습니다. 두 가지 모두 NSOverwriteMergePolicy로 정의 된 정책을 가지고 있습니다. 이미 동기화 문제가 있습니다. 나는 종종 백그라운드 NSyncagedObjects 서버 데이터에서 백그라운드 동기화에서 구식이며, 결국 그들을 잃게 데이터의 손실을 일으키는 것을 목격합니다.

모든 규칙을 방문 할 수있는 곳이 있습니까? & 우선 순위는 우선 순위에 따라 달라집니다.

병합 정책에 관한 모든 문서를 보았지만 SAVE 또는 REFRESH에 영향을 미치는지 혼란 스럽습니다. 또한 어느 정도까지는 이것이 매우 혼란 스럽습니다. 예를 들어, Apple Docs 상태이 NSMergeByPropertyObjectTrumpMergePolicy에 대한 :

메모리 변경을 trumping 외부 변화, 영구 저장소의 객체의 버전 개인 속성에 의해 현재의 메모리 버전 사이에 충돌을 병합 정책 . 병합은 개별 속성별로 수행됩니다.

외부 소스와 메모리 모두에서 변경된 속성의 경우 메모리 내 변경 사항이 외부 소스보다 우선합니다.

원하는 컨텍스트에서 수정하거나 변경하지 않을 때 원하는 속성이 변경되거나 영향을받지 않도록하는 방법은 무엇입니까?

답변

1

TL : DR : 병합 정책이 악의입니다. 하나의 동기식 방식으로 코어 데이터에만 기록해야합니다.

전체 설명 : 개체가 두 개의 다른 컨텍스트에서 동시에 변경되는 경우 core-data는 수행 할 작업을 알 수 없습니다. mergePolicy를 설정하여 어떤 변화가 승리해야 하는지를 설정할 수 있지만 실제로는 좋은 해결책이 아닙니다. 그렇게하면 데이터가 손실 될 수 있기 때문입니다. 많은 전문가들이 오랫동안 문제를 해결해 온 방식은 쓰기 대기열에 작업 대기열을 두어 한 번에 하나의 쓰기 만 수행하고 주 스레드에서 다른 컨텍스트를 읽기 전용으로 사용하는 것이 었습니다 . 이렇게하면 병합 충돌이 발생하지 않습니다. (이 설정에 대한 자세한 설명은 https://vimeo.com/89370886을 참조하십시오).

NSPersistentContainer으로 설정하는 것은 매우 쉽습니다. 핵심 데이터 관리자에서

_persistentContainerQueue = [[NSOperationQueue alloc] init]; 
_persistentContainerQueue.maxConcurrentOperationCount = 1; 

NSOperationQueue

를 만들고이 큐를 사용하는 모든 쓰기 작업을 수행합니다 당신이 enqueueCoreDataBlock를 호출 할 때 블록이 어떤 병합 충돌이 없다는 것을 보장하기 위해 대기열에

- (void)enqueueCoreDataBlock:(void (^)(NSManagedObjectContext* context))block{ 
    void (^blockCopy)(NSManagedObjectContext*) = [block copy]; 

    [self.persistentContainerQueue addOperation:[NSBlockOperation blockOperationWithBlock:^{ 
     NSManagedObjectContext* context = self.persistentContainer.newBackgroundContext; 
     [context performBlockAndWait:^{ 
      blockCopy(context); 
      [context save:NULL]; //Don't just pass NULL here. look at the error and log it to your analytics service 
     }]; 
    }]]; 
} 

. 그러나 viewContext에이 설정을 무시하면 쓸 수 있습니다. 마찬가지로 작성한 다른 컨텍스트 (newBackgroundContext 또는 performBackgroundTask)는 쓰기 대기열 외부에 있기 때문에 읽기 전용으로 취급해야합니다.