지금 MagicalRecord를 무시해 봅시다. 여러 스레드에서 코어 데이터를 사용하려면 몇 가지 사항을 알고 있어야합니다.
- 절대로 스레드간에
NSManagedObject
을 전달하지 마십시오. 대신 원하는 객체에 대해 NSManagedObjectID
을 전달하고 백그라운드 스레드에서 다시 가져옵니다.
- 책임감을 가지고
NSManagedObjectContext
을 빌드하십시오. 즉, initWithConcurrencyType:
의 의미를 알아야합니다. 우리는 그것에 들어갈 것입니다.
메인 스레드
주 NSManagedObjectContext
이 NSMainQueueConcurrencyType
의 동시성 유형으로 구축되어야한다. 이렇게하면 직렬 작업 수행을 위해 대기열에 내장 된 컨텍스트를 활용할 수 있습니다. 백그라운드 스레드가 주 컨텍스트와 상호 작용할 때마다 performBlock
또는 performBlockAndWait
을 사용하여 작업해야합니다.
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
배경 스레드는 백그라운드 스레드에서 작업을 수행 할 때마다
, 새로운 컨텍스트를 회전해야합니다. 스레드간에 컨텍스트를 공유하면 안됩니다. 주 스레드 컨텍스트에 대한 참조를 작업에 전달하고 작업이 시작되면 백그라운드 컨텍스트를 작성하십시오. 이렇게하면 작업을 수행 할 스레드에 빌드됩니다.
- (NSManagedObjectContext *)newBackgroundManagedObjectContext
{
// Create new context with private concurrency type
NSManagedObjectContext *newContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[newContext setParentContext:self.mainContext];
// Optimization
[newContext setUndoManager:nil];
return newContext;
}
이 배경 컨텍스트를 스크래치 패드로 생각하십시오. 당신이 무엇을 하든지 당신이 구원 할 때까지 거기에 머무를 것입니다. parentContext를 설정 했으므로 백그라운드 컨텍스트에 대한 저장은 주 컨텍스트로 변경 내용을 병합합니다. 그러면 NSFetchedResultsController
이 업데이트되지만 저장을 호출하지 않았으므로 데이터가 아직 보존되지 않았습니다.KVO 대기열에서 저장 블록을 대기열로 묶어 주 컨텍스트에서 저장을 호출 할 수 있습니다.
[self performBlock:^{
NSError *error;
[self save:&error];
if (error) {
// handle errors
}
}];
MagicalRecord가 모든 컨텍스트 관리 작업을 처리합니다. – JonahGabriel
MagicalRecord는 블록으로 배경 작업을 관리합니다. Core Data를 둘러싼 타사 래퍼와 마찬가지로 Core Data만으로는 본질적으로 유연성이 떨어집니다. 후드 아래에서 무슨 일이 벌어지고 있는지 설명하기위한 나의 시도가 여전히 유용 할 것입니다. – Drewsmits
아주 잘 설명! 나는 이것이 받아 들여진 대답이어야한다고 생각한다. –