4

대기열에서 실행되는 동안 엔티티를 만들고 가져 오는 NSOperations이 있습니다.Magical Record 별도의 스레드에서 엔티티 생성/가져 오기

  1. 단순히 기본 컨텍스트를 사용하여 만들거나 내가 메인 스레드에없는 새 스레드에서 오전부터이 허용/권장되지 않는 NSOperations에 엔티티를 생성 할 때? 이 스레드에서 새 엔터티를 만드는 경우 기본 컨텍스트로 다시 병합하는 가장 좋은 방법은 무엇입니까 (저장소에 저장하지 않음)?

  2. 이러한 스레드에서 페치 할 때 해당 엔티티의 데이터를 가져와야합니다. 이 작업을 수행 한 다음 기본 컨텍스트에 병합하는 방법에 관해서는 손해보고 있습니다.

아니면 저장할 때 어떤 스레드를 가져 오거나 만들지는 정말로 중요하지 않습니까?

업데이트 및 삽입의 기본 컨텍스트를 모니터링하는 NSFetchedResultsController가 있기 때문에 위의 기본 컨텍스트를 말합니다. 현재 내 솔루션은 주 스레드에서이 모든 작업을 수행하고 있지만 앱이 지금 실행중인 데이터 양과 함께 크롤링을 시작합니다.

또한 작업 대기열 수를 모니터링하는 클래스가 있습니다 (KVO를 통해). 일단 0이되면 저장을 실행합니다. 위의 모든 NSOperations가 현재 수행중인 것처럼 실행 된 후에 만 ​​저장하는 것을 선호합니다. 도와 주셔서 감사합니다.

답변

8

지금 MagicalRecord를 무시해 봅시다. 여러 스레드에서 코어 데이터를 사용하려면 몇 가지 사항을 알고 있어야합니다.

  1. 절대로 스레드간에 NSManagedObject을 전달하지 마십시오. 대신 원하는 객체에 대해 NSManagedObjectID을 전달하고 백그라운드 스레드에서 다시 가져옵니다.
  2. 책임감을 가지고 NSManagedObjectContext을 빌드하십시오. 즉, initWithConcurrencyType:의 의미를 알아야합니다. 우리는 그것에 들어갈 것입니다.

메인 스레드

NSManagedObjectContextNSMainQueueConcurrencyType의 동시성 유형으로 구축되어야한다. 이렇게하면 직렬 작업 수행을 위해 대기열에 내장 된 컨텍스트를 활용할 수 있습니다. 백그라운드 스레드가 주 컨텍스트와 상호 작용할 때마다 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 
    } 
}]; 
+1

MagicalRecord가 모든 컨텍스트 관리 작업을 처리합니다. – JonahGabriel

+1

MagicalRecord는 블록으로 배경 작업을 관리합니다. Core Data를 둘러싼 타사 래퍼와 마찬가지로 Core Data만으로는 본질적으로 유연성이 떨어집니다. 후드 아래에서 무슨 일이 벌어지고 있는지 설명하기위한 나의 시도가 여전히 유용 할 것입니다. – Drewsmits

+0

아주 잘 설명! 나는 이것이 받아 들여진 대답이어야한다고 생각한다. –