2012-04-12 2 views
5

저장 문맥 후 작동하지 :NSSortDescriptor 나는 다음과 같이 정의 NSManagedObjectContext에 GCD 파견 큐에서 작업을하고 있어요

NSManagedObjectContext *context = [[self alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
[context setParentContext:[NSManagedObjectContext MR_defaultContext]]; 
return context; 

후 :

- (NSManagedObjectContext *)backgroundContext 
{ 
    if (backgroundContext == nil) { 
     self.backgroundContext = [NSManagedObjectContext MR_contextThatNotifiesDefaultContextOnMainThread]; 
    } 
    return backgroundContext; 
} 

MR_contextThatNotifiesDefaultContextOnMainThread 것은 MagicalRecord에서하는 방법입니다 내 객체를 가져 와서 올바른 대기열 위치를 지정하면 로그에 기록되고 순서가 올바른 것입니다. 그러나 두 번째 로그는 완전히 무작위로 보이며 정렬 설명자는 분명히 작동하지 않습니다.

문제점을 [self.backgroundContext save:&error]으로 좁혔습니다. 배경 컨텍스트를 저장 한 후 정렬 설명자가 손상됩니다.

dispatch_group_async(backgroundGroup, backgroundQueue, ^{ 
    // ... 

    for (FooObject *obj in fetchedObjects) { 
     // ... 
     obj.queuePosition = [NSNumber numberWithInteger:newQueuePosition++]; 
    } 

    NSFetchRequest *f = [NSFetchRequest fetchRequestWithEntityName:[FooObject entityName]]; 
    f.predicate = [NSPredicate predicateWithFormat:@"queuePosition > 0"]; 
    f.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"queuePosition" ascending:YES]]; 
    NSArray *queuedObjects = [self.backgroundContext executeFetchRequest:f error:nil]; 
    for (FooObject *obj in queuedObjects) { 
     DLog(@"%@ %@", obj.queuePosition, obj.title); 
    } 

    if ([self.backgroundContext hasChanges]) { 
     DLog(@"Changes"); 
     NSError *error = nil; 
     if ([self.backgroundContext save:&error] == NO) { 
      DLog(@"Error: %@", error); 
     } 
    } 

    queuedObjects = [self.backgroundContext executeFetchRequest:f error:nil]; 
    for (FooObject *obj in queuedObjects) { 
     DLog(@"%@ %@", obj.queuePosition, obj.title); 
    } 

}); 

정렬 설명자가 작동하지 않는 이유는 모르겠지만 핵심 데이터 전문가는 도움을 원합니다.

업데이트 :

문제는 아이폰 OS 4에 나는 이유는 스레드 격리 및 개인 큐 모드의 차이 어딘가에 생각 발생하지 않습니다. MagicalRecord는 자동으로 다르게 동작하는 것처럼 보이는 새로운 동시성 패턴을 사용합니다.

업데이트 2 :

문제는 배경 컨텍스트의 선방을 추가하여 해결되었습니다

if ([[NSManagedObjectContext MR_contextForCurrentThread] hasChanges]) { 
    DLog(@"Changes"); 
    NSError *error = nil; 
    if ([[NSManagedObjectContext MR_contextForCurrentThread] save:&error] == NO) { 
     DLog(@"Error: %@", error); 
    } else { 
     NSManagedObjectContext *parent = [NSManagedObjectContext MR_contextForCurrentThread].parentContext; 
     [parent performBlockAndWait:^{ 
      NSError *error = nil; 
      if ([parent save:&error] == NO) { 
       DLog(@"Error saving parent context: %@", error); 
      } 
     }]; 
    } 
} 

업데이트 3 :

MagicalRecord가 반복적으로 저장하는 방법을 제공을 문맥, 이제 내 코드는 다음과 같습니다 :

처음에 그것을 사용하지 않는 날

부끄러운 ...

는 그러나, 나는이 도움이 이유을 모르는 및 설명을 얻을 싶어요.

답변

2

을 참조하십시오.

따라서 iOS5에서는 MagicalRecord가 여러 관리 객체 컨텍스트의 새로운 개인 대기열 메소드를 사용하도록 설정됩니다. 즉, 하위 컨텍스트의 저장은 부모에게만 저장을 푸시합니다. 더 이상 부모가없는 부모가 저장하는 경우에만 저장이 해당 저장소에 유지됩니다. 이것은 아마도 MagicalRecord 버전에서 일어난 일일 것입니다.

MagicalRecord가 최신 버전에서이 문제를 처리하려고 시도했습니다. 즉, 개인 큐 모드와 스레드 격리 모드 중 하나를 선택하려고합니다. 당신이 알았 듯이, 그것은 너무 잘 작동하지 않습니다.iOS4와 iOS5에서 코드를 작성하는 진정한 호환 방법 (복잡한 전처리 기가없는 등)은 고전적인 스레드 분리 모드를 사용하는 것입니다. 1.8.3 태그의 MagicalRecord는 이것을 지원하며, 둘 다 작동해야합니다. 2.0부터는 여기에서 전용 대기열이됩니다.

그리고 MR_save 메소드를 보면 hasChanges 검사를 수행하고있는 것을 볼 수 있습니다.이 검사는 또한 이후에 불필요 할 수도 있습니다. 핵심 데이터 내부도이를 처리 할 수 ​​있습니다.) 어쨌든, 적은 코드를 작성하고 유지해야합니다 ...

+1

귀하의 의견을 보내 주셔서 감사 드리며, 스레드 분리만을 사용하여 실험 해 보았습니다.하지만 iOS 5에서 개인 큐를 사용하고 싶습니다. 테스트 중에 버그를 발견했습니다. 부모 컨텍스트의 저장은 자식 컨텍스트의 스레드에서 호출되므로 GCD 컨텍스트에서 재귀 적으로 저장할 때 문제가 발생합니다. 내가 풀 요청을 제출했습니다 : https://github.com/magicalpanda/MagicalRecord/pull/159 – tim

-2

CoreData는 안전한 스레드 프레임 워크가 아니며 각 스레드 (작업 대기열)에 대해 핵심 데이터는 차이 컨텍스트를 사용합니다. 내가 MagicalRecord을 쓴 이후로 내가 언급하려고합니다 다음과 같은 우수한 기록을

http://www.duckrowing.com/2010/03/11/using-core-data-on-multiple-threads/

+0

backgroundContext는 GCD 블록에서 초기화되며 ManagedObject 또는 ManagedObjectContext는 스레드 테두리를 교차하지 않으므로 여기서 내 문제라고 생각하지 않습니다. – tim

1

부모 설치 프로그램이 작동하지 않는 실제적인 근본적인 이유는 부모 컨텍스트가 아직없는 경우 정렬 설명자를 사용하여 하위 컨텍스트에서 가져 오는 것입니다 저장 저장 : 당신이 중첩 된 상황을 피할 수있는 방법이 있다면,

NSSortdescriptor ineffective on fetch result from NSManagedContext

을 그들은 여전히 ​​매우 버그가로를 방지 할 당신은 가능성이 추정 성능 향상에 실망 될 것입니다, 참조 또한 : http://wbyoung.tumblr.com/post/27851725562/core-data-growing-pains