2012-07-25 5 views

답변

4

당신은 멀티 스레드 방식으로 코어 데이터를 사용할 수 있지만 approaches recommended by Apple 중 하나를 따라야합니다 특히

The pattern recommended for concurrent programming with Core Data is thread confinement: each thread must have its own entirely private managed object context.

There are two possible ways to adopt the pattern:

Create a separate managed object context for each thread and share a single persistent store coordinator. This is the typically-recommended approach.

Create a separate managed object context and persistent store coordinator for each thread. This approach provides for greater concurrency at the expense of greater complexity (particularly if you need to communicate changes between different contexts) and increased memory usage.

이에서

Using thread confinement, you should not pass managed objects or managed object contexts between threads. To “pass” a managed object from one context another across thread boundaries, you either:

Pass its object ID (objectID) and use objectWithID: or existingObjectWithID:error: on the receiving managed object context. The corresponding managed objects must have been saved—you cannot pass the ID of a newly-inserted managed object to another context.

Execute a fetch on the receiving context. These create a local version of the managed object in the receiving context.

는, 당신이 관리되는 개체를 만들 수 없습니다 것을 계속된다 스레드 (자신의 컨텍스트와 함께)에 다음 다른에 저장합니다.

그래서 원하는 것을 이루려면 스레드간에 관리 대상 개체 컨텍스트 또는 영구 저장소 조정자를 공유해야합니다. 이 경우 제대로 일관성없는 상태에 들어 상점을 방지하기 위해 기술을 잠금 사용해야합니다

If you share a managed object context or a persistent store coordinator between threads, you must ensure that any method invocations are made from a thread-safe scope. For locking, you should use the NSLocking methods on managed object context and persistent store coordinator instead of implementing your own mutexes. These methods help provide contextual information to the framework about the application's intent—that is, in addition to providing a mutex, they help scope clusters of operations.

나는 앱의 디자인을 수정할 수있는 기회가 있다면,이 경로를 이동하는 것이 좋습니다 않을 것이다

있도록 핵심 데이터 객체에 대한 잠금 및 동기화가 필요하지 않습니다.

1

당신이 바로 중첩 된 상황과에 맞는 요구하고있다. 비공개 대기열 컨텍스트를 작성하고이를 영구 저장소 조정자에 직접 첨부하십시오. 간단하다. 이제 ...

managedObjectContext = [[NSManagedObjectContext alloc] init]; 

이로 교체 ... 대신에,

workerManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 

을 현재의 코드를 가지고, 그리고, 당신은 실행하는 새로운 MOC와 전통 구속 MOC를 대체했다 자체 동시성 대기열을 사용합니다.

managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 
managedObjectContext.parent = workerManagedObjectContext; 

이 의미 ...

는 메인 스레드에서 사용할 수있는 컨텍스트를 얻으려면, 당신은 다른 관리 개체 컨텍스트를 생성하고, 방금 만든 하나의 자식 수 있도록 당신이 할 수있는 그 이전처럼 managedObjectContext를 사용하십시오. 그러나 지금은 상점에 직접가는 대신 중개 컨텍스트를 거칩니다. 부모 컨텍스트는 자체 백그라운드 스레드에서 작업을 수행합니다.

따라서 모든 managedObjectContext를 원하는대로 변경할 수 있습니다. 이 저장 시간이 올 때, 당신은 ... 같은 것을 할

static void saveManagedObjectContext(NSManagedObjectContext *moc, void(^completionBlock)(NSError *error)) { 
    [moc performBlock:^{ 
     NSError *error = nil; 
     if (moc.hasChanges && [moc save:&error] && moc.parentContext) { 
      saveManagedObjectContext(moc.parentContext, completionBlock); 
     } else { 
      completionBlock(error); 
     } 
    }]; 
} 

편집

당신이 보편적이를 사용하려는 경우, 당신은 쉽게 NSManagedObjectContext에 카테고리에 추가하고 있습니다 그냥 전화 해 ...

[managedObjectContext saveWithCompletionBlock:^(NSError *error){ 
    if (error) { 
     // Handle the error 
     return; 
    } 
    // Handle success... 
}]; 
0

Apple은 별도의 스레드에 별도의 컨텍스트를 사용하는 것이 좋습니다. 저장을 호출하면 실제 데이터베이스에 저장되는 컨텍스트 상태가됩니다. 주 스레드 변경 사항이 백그라운드 스레드에 반영되도록하려면 백그라운드 스레드 컨텍스트를 주 스레드 컨텍스트와 병합하고 저장을 호출하십시오.

관련 문제