2011-02-07 3 views
5

현재 NSOperation을 사용하여 백그라운드에서 데이터를 가져 오는 NSPersistentDocument 하위 클래스로 작업하고 있습니다. 문서에 따라 백그라운드 작업에 저장하고 -mergeChangesFromContextDidSaveNotification:을 사용하여 주 스레드의 NSManagedObjectContext에 알림을 전파 한 후 NSManagedObjectContextDidSaveNotification을 관찰하고 있습니다.핵심 데이터 및 NSOperation

모든 것이 제대로 작동하지만 데이터를 새 문서로 가져 오는 사용자에게는 이상한 워크 플로가 제공됩니다. 가져 오기를 수행하기 전에 빈 문서를 저장해야합니다. 그렇지 않으면 문서에 NSPersistentStoreCoordinator의 URL이 구성되어 있지 않으므로 -save:이 실패합니다. "새로운 문서 설정"마법사와 다른 방법이 없습니다. 가져 오기 전에 -writeToURL:ofType:forSaveOperation:originalContentsURL:error:이 호출되도록합니다.

또한 백그라운드에서 가져 오기 작업을 수행하면 기본 스레드에서 NSUndoManager을 사용할 수 없습니다. (나는 관리 대상 객체 컨텍스트의 실행 취소 관리자를 스레드에서 공유하는 것이 안전하지 않다고 가정합니다.) 사용자의 관점에서 볼 때 가져 오는 동안 생성 된 모든 새 객체를 실행 취소 할 방법이 없습니다.

핵심 데이터 프로그래밍 가이드과 Marcus Zarra의 책을 모두 읽었지만 아직 프레임 워크의이 부분에 익숙하지 않습니다. 바라기를 바란 점은 간과 했으므로, 이러한 제한에 내 애플리케이션을 적용 할 것입니다. Core Data의 이점이 사용자 인터페이스의 한계를 훨씬 능가합니다.

감사합니다. 파일이 저장 선택 후,

NSPersistentStoreCoordinator *persistentStoreCoordinator = [self.managedObjectContext persistentStoreCoordinator]; 
if ([[persistentStoreCoordinator persistentStores] count] == 0) { 
    // create an in-memory store to use temporarily 
    NSError *error; 
    NSPersistentStore *persistentStore = [persistentStoreCoordinator addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:&error]; 
    if (! persistentStore) { 
     NSLog(@"error = %@", error); // TODO: better error handling 
    } 
} 

다음 : -

아래 피터 Hosey의 제안을 바탕으로

, 내가 가져 오기 전에 임시 영구 저장소를 만들려면 다음 코드를 추가 패널, 임시 영구 저장소는 선택된 URL에서 SQLite는 저장소로 마이그레이션 :

- (BOOL)writeToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName forSaveOperation:(NSSaveOperationType)saveOperation originalContentsURL:(NSURL *)absoluteOriginalContentsURL error:(NSError **)error 
{ 
    NSPersistentStoreCoordinator *persistentStoreCoordinator = [self.managedObjectContext persistentStoreCoordinator]; 
    for (NSPersistentStore *persistentStore in [persistentStoreCoordinator persistentStores]) { 
     if (persistentStore.type == NSInMemoryStoreType) { 
      // migrate the in-memory store to a SQLite store 
      NSError *error; 
      NSPersistentStore *newPersistentStore = [persistentStoreCoordinator migratePersistentStore:persistentStore toURL:absoluteURL options:nil withType:NSSQLiteStoreType error:&error]; 
      if (! newPersistentStore) { 
       NSLog(@"error = %@", error); // TODO: better error handling 
      } 
     } 
    } 

    return [super writeToURL:absoluteURL ofType:typeName forSaveOperation:saveOperation originalContentsURL:absoluteOriginalContentsURL error:error]; 
} 
+1

Mac의 경우 메모리 저장소를 사용할 수 없으며 준비가되었을 때 파일 기반 저장소를 사용하도록 컨텍스트를 전환 할 수 없습니까? 위의 코드는 실행 취소 문제도 해결할 것입니다. 필요한 경우 전체 컨텍스트 스택을 제거하면됩니다. 내가이 글을 쓰는 동안 모든 사람들이 똑같은 것을 쓰고있는 것 같다. – Jonathan

답변

5

아무도 Core Data 전문가는 아니지만 문서에서 알 수있는 것으로부터 사용자가 (자신의 시간에) 문서를 저장할 때까지 메모리 내 저장소로 시작하는 것이 좋습니다. 그런 다음 코디네이터 a migratePersistentStore:toURL:options:withType:error: message을 보내 인 메모리 저장소에서 새로운 진정한 영구 저장소로 변경하십시오.이 문서에서 몇 가지 필수 세부 정보를 확인하십시오 (특히 이전하는 상점의 운명과 관련하여).

+0

감사합니다 피터! 마이그레이션은 누락 된 퍼즐 조각이었습니다. 위의 게시물을 업데이트했습니다. – chockenberry

2

워크 플로우에 내 첫번째 생각은/부분을 절약 될하는 persiste 경우 nt 저장소가 임시로 인 메모리 저장소를 만들도록 문서에 대해 아직 만들어지지 않았으므로 가져온 데이터가 해당 저장소에 대신 저장됩니다 (문서/창은 여전히 ​​더티로 표시되지만). 그런 다음 사용자가 실제로 문서를 저장하면 코디네이터를 다시 구성하여 메모리 내장 저장소를 제거하고 디스크 저장소로 교체하여 모든 추가 저장 내용을 디스크로 옮깁니다.

0

코디네이터를 설정할 때 임시 파일 URL을 설정해 보셨습니까? 주 스레드에서 -mergeChangesFromContextDidSaveNotification :을 실행 취소 할 수 있어야합니다. 백그라운드 스레드에서 MOC의 실행 취소 관리자를 등록 할 필요가 없습니다.

+0

좋은 해결책 Daniel, Peter & Brian과 마찬가지로 단순히 메모리 내장 저장소를 만드는 것만으로 더 깔끔하고 더 빨리 말할 것도 없다. 그러나 우리가 매우 큰 데이터 세트에 대해 이야기한다면 대안이되어야합니다. – Jonathan

2

저는 Mac에 익숙하지 않지만 사용자가 저장하기 전에 메모리 내 영구 저장소를 사용하고 그 작업 후에 SQL/plist 저장소를 추가 할 수 있습니다.

표준 임시 디렉토리에 디스크상의 영구 저장소를 생성하고 사용자가 저장하기 위해 클릭 할 때 가로 질러 이동하는 것이 더 좋을 수도 있습니다.