2013-03-11 2 views
0

코어 데이터 저장 및 멀티 스레드 지원을 위해 Magical Record를 사용하고 있습니다.코어 데이터를 매직 레코드로 저장

GCD로 새 스레드를 시작합니다. 이 새 스레드에서 엔티티가 존재하는지 확인합니다. 그렇지 않다면 새로운 것을 만들고 그것을 저장하고 싶습니다.

saveUsingCurrentThreadContextWithBlock^(NSManagedObjectContext *localContext){} 주 스레드가 아닌 스레드에서 호출되는 경우 주 스레드로 돌아가서 저장합니까?

또는 새 스레드에 컨텍스트를 전달해야합니까?

편집 : '

MBProgressHUD *HUD = [MBProgressHUD showHUDAddedTo:self.mapView animated:YES]; 

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 

    Person *person = [Person MR_findFirstByAttribute:NAME withValue:self.user.username]; 

    if (person == NULL) { 
     NSLog(@"SEPERATE THREAD | person %@ does not exist, creating", self.user.username); 
     person = [Person MR_createEntity]; 
     person.name = self.user.username; 
     person.uid = self.user.UID; 

     [[NSManagedObjectContext MR_contextForCurrentThread] MR_saveOnlySelfWithCompletion:^(BOOL success, NSError *error) { 
      [MBProgressHUD hideHUDForView:self.mapView animated:YES]; 

      Person *person = [Person MR_findFirstByAttribute:NAME withValue:self.user.username]; 

      if (person) { 
       NSLog(@"COMPLETION BLOCK | person exists: %@", person.name); 
      } 
     }]; 
    } 
    else { 
     NSLog(@"SEPERATE THREAD | person %@ does", self.user.username); 

      dispatch_async(dispatch_get_main_queue(), ^{ 
       [MBProgressHUD hideHUDForView:self.mapView animated:YES]; 
      }); 
    } 
}); 

이 (절약이 방법은 지속성 아니라, 내가 응용 프로그램을 다시 시작하고 내가 할 수있는 : 주 스레드에서

, 나는 MBProgress 표시기를 만들고 새 스레드를 생성 Person 엔티티를 찾으십시오) :

2013-03-12 14:25:44.014 SEPERATE THREAD | person iDealer does not exist, creating 
2013-03-12 14:25:44.014 SEPERATE THREAD | thread: <NSThread: 0x84ca720>{name = (null), num = 4} 
2013-03-12 14:25:44.015 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x840ec30) → Saving <NSManagedObjectContext (0x840ec30): *** UNNAMED ***> on *** BACKGROUND THREAD *** 
2013-03-12 14:25:44.015 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x840ec30) → Save Parents? 0 
2013-03-12 14:25:44.015 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x840ec30) → Save Synchronously? 0 
2013-03-12 14:25:44.016 -[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x840ec30) Context UNNAMED is about to save. Obtaining permanent IDs for new 1 inserted objects 
2013-03-12 14:25:44.132 __70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke21(0x840ec30) → Finished saving: <NSManagedObjectContext (0x840ec30): *** UNNAMED ***> on *** BACKGROUND THREAD *** 
2013-03-12 14:25:44.134 COMPLETION BLOCK | thread: <NSThread: 0x8435f30>{name = (null), num = 1} 
2013-03-12 14:25:44.134 COMPLETION BLOCK | person exists: iDealer 

답변

7

좋아, 나는 그것이 작동있어 :

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    Person *person = [Person MR_findFirstByAttribute:NAME withValue:self.user.username]; 

    if (person == NULL) { 
      [MagicalRecord saveUsingCurrentThreadContextWithBlock:^(NSManagedObjectContext *localContext){ 
       Person *localPerson = [Person MR_createInContext:localContext]; 
       localPerson.name = self.user.username; 

      } completion:^(BOOL success, NSError *error){ 
       [MBProgressHUD hideHUDForView:self.mapView animated:YES]; 
      }]; 
    } 
    else { 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [MBProgressHUD hideHUDForView:self.mapView animated:YES]; 
     }); 
    } 
}); 

이 작동하고 저장합니다. 나는이 방법으로 casademora가 의미하는 것이 정확하지 않다는 것을 확신하지 못한다. 나는이 방법을 사용하는 것의 차이점을 saveOnlySelf:completion: 방법으로 결정할 수 없다.

saveOnlySelf으로 영구 저장소에 컨텍스트를 저장할 수없는 것처럼 보입니다. 내 질문에 코드로 만들면 문맥에 배치됩니다. Person 엔티티에 대한 검색을 수행하면 찾을 수 있습니다. 하지만 일단 앱을 종료하고 다시 시작하면 Person 개체가 표시되지 않습니다. 스레드 컨텍스트를 주/기본 컨텍스트에 저장하거나 병합하는 것처럼 느껴졌지만 그 컨텍스트는 저장되지 않았습니다.

편집 :

좀 더 MR 놀아 후에는 saveOnlySelf 방법 중 하나가 아닌 메인 스레드에서 사용하는 경우, 그것은 기본 컨텍스트에 로컬 컨텍스트를 병합 것으로 보이지만 그렇지 않습니다 영구 저장소에 저장하십시오. 완료 후에 기본 컨텍스트를 확인하면 새 엔티티가 실제로 존재합니다. 그러나 일단 앱을 종료하고 다시 실행하면 앱이 존재하지 않습니다.

컨텍스트를 병합하고 저장소에 저장하려면 saveToPersistentStoreAndWait 형식 메서드 중 하나를 호출해야합니다.

+0

'saveUsingCurrentThreadContextWithBlock'내부의 코드가 백그라운드 스레드에서 실행되고 있습니다 (MR 문서 당) - 여기에 GCD를 정확히 사용하는 이유는 무엇입니까? – Petar

-1

예, 완료 블록이 주 스레드에서 실행됩니다. 예를 들면 다음과 같습니다.

NSOperationQueue *newQueue = [[NSOperationQueue alloc] init]; 
[newQueue addOperationWithBlock:^{ 
    [MagicalRecord saveUsingCurrentThreadContextWithBlock:^(NSManagedObjectContext *localContext) { 
     // save something 
    } completion:^(BOOL success, NSError *error) { 
     // this will execute in the main thread 
    }]; 
}]; 
2

현재 버전의 MagicalRecord에서는 완료 블록이 주 스레드로 돌아갑니다. 그러나 여기에 나와있는 방법이 잘못되었습니다. save 메소드의 더 명백한 변형이 있습니다 :

saveOnlySelf:completion: 
saveToPersistentStore:completion: 

현재 버전에서이 메소드를 살펴보십시오. 다시 말하면 주어진 localContext의 관리 객체 만 사용해야합니다. 작업 블록은 모든 스레드/대기열에서 실행될 수 있으며이 경우 코어 데이터에 대해 적절한 스레드 관리 규칙을 계속 사용하고자합니다.

+1

어, 주 컨텍스트에만 저장합니까? 주 컨텍스트를 저장합니까? 아니면 수동으로해야합니까? – Padin215

+1

여기에는 기본 컨텍스트가 저장되는 두 가지 방법이 있습니다. 1) 하위 컨텍스트는 기본 컨텍스트의 하위 컨텍스트이고 2) 하위 컨텍스트는 기본 컨텍스트의 먼 자식이며 saveToPersistentStore : completion :이 호출됩니다. – casademora