2012-06-29 8 views
4

코어 데이터 엔티티 'MyGalleryPhoto'에서 쿼리하는 NSFetchedResultsController가 있습니다.MagicalRecord + Core objectID 문자열 비교가 작동해도 컨텍스트간에 개체를 찾을 수 없습니다.

일부 개체를 삭제하려고하는데 문제가 발생합니다. MagicalRecord를 사용하고 있습니다. 내보기에서 잘 작동합니다 코드에서 내 원래 시도입니다. 코드가 실행되는 시점에 객체는 fetchedResultsController에 표시되기 때문에 분명히 존재합니다.

[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext) { 

    for (MyGalleryPhoto *myGalleryPhoto in [self.fetchedResultsController.fetchedObjects objectsAtIndexes: self.selectedIndexes]) { 

     NSError *error = nil; 
     MyGalleryPhoto *localMyGalleryPhoto = (MyGalleryPhoto *) [localContext existingObjectWithID: myGalleryPhoto.objectID error: &error]; 

     NSLog(@"error: %@:%@", [error localizedDescription], [error userInfo]); 
     NSLog(@"mygp: %@", [localMyGalleryPhoto description]); 

     [localMyGalleryPhoto deleteInContext: localContext]; 
    } 

} completion:^(void){ 
}]; 

이 코드는 작동하지 않습니다. myGalleryPhoto 항목을 찾을 수 없으며 반환 된 오류 : "작업을 완료 할 수 없습니다. (코코아 오류 133000.)"또한 MR_inContext, 그냥 existingObjectWithId 호출하여 사용하려고 : 오류 :.

난장판을 많이 뒤쫓아 가면서이 나쁜 프랑켄슈타인의 괴물을 생각해 냈습니다. 엔티티에서 모든 레코드를 가져 와서 ObjectID의 문자열 표현을 비교합니다. 이것은 잘 작동합니다. 왜? 오늘 GitHub에서 다운로드 한 MagicalRecord 사본, XCode 최신, 최신 SDK 등을 사용하고 있습니다. the documentation에 기재된

[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext) { 

    NSArray *allMyGalleryPhotos = [MyGalleryPhoto findAllInContext: localContext]; 

    for (MyGalleryPhoto *myGalleryPhoto in [self.fetchedResultsController.fetchedObjects objectsAtIndexes: self.selectedIndexes]) { 

     MyGalleryPhoto *myGalleryPhotoToDelete = nil; 

     for (MyGalleryPhoto *existingMyGalleryPhoto in allMyGalleryPhotos) { 

      NSString *existingURLString = [[existingMyGalleryPhoto.objectID URIRepresentation] absoluteString]; 
      NSString *URLString = [[myGalleryPhoto.objectID URIRepresentation] absoluteString]; 

      NSLog(@"ExistingURLString: %@", existingURLString); 
      NSLog(@"URLString: %@", URLString); 

      if ([URLString isEqualToString: existingURLString]) { 
       myGalleryPhotoToDelete = existingMyGalleryPhoto; 
      } 
     } 

     if (myGalleryPhotoToDelete) [myGalleryPhotoToDelete deleteInContext: localContext]; 

    } 

} completion:^(void){ 
}]; 

답변

5

코코아 오류 13000은 참조 무결성 에러이다. 이는 상점에 존재하지 않는 오브젝트를 찾고 있음을 의미합니다. 보다 실용적인 수준에서, 즉, 컨텍스트 (하나 이상의 Managed Object Context가 있다고 가정하고 있음)가 동기화되지 않았다는 것을 의미합니다. 즉, 하나의 컨텍스트에 새 개체를 추가 한 반면 다른 컨텍스트에는 이전 컨텍스트가 저장되지 않았으므로 해당 개체가 없습니다.

코드에 관해서는 첫 번째 예제에서 볼 수있는 첫 번째 문제는 처음부터 스레드 경계를 넘고 있다는 것입니다. fetchedResultsController에는 다른 컨텍스트의 객체에 대한 참조가 있습니다 (기본 컨텍스트로 가정합니다). saveInBackground가 호출 될 때마다 사용할 새로운 컨텍스트를 제공하지만 해당 블록을 백그라운드 스레드에 넣습니다. 새로운 버전의 Core Data에서도 스레드 경계를 넘으면 무작위로 문제를 추적하기가 어렵습니다.

첫 번째 (더 간단한) 코드 블록에서 수행하려는 작업이 애플리케이션에서 제거하려는 사진 개체의 컬렉션을 갖고 있다면 요점이 있습니다. 나는이 대신 같은 것을 할 것입니다 :

NSPredicate *objectsToDelete = [NSPredicate predicateWithFormat:@"self in %@", self.fetchedResultsController.fetchedObjects]; 

[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *)localContext 
{ 
    [MyGalleryPhoto deleteAllMatchingPredicate:objectsToDelete inContext:localContext]; 
}]; 

deleteAllMatchingPredicate 방법은 (당신이 코드의 첫 번째 블록에 일을하지 않았다) 그래서 그들은 삭제할 수 있습니다 올바른 컨텍스트에있는 개체의 조회를해야한다. 또한 오류로로드 할 객체를 설정하므로 모든 것을 메모리에로드하지 않고 즉시 삭제합니다. 필요로하는 것만로드하고 더 이상로드하지 않습니다.

이 경우에는 existingObjectWithID를 사용하지 않을 것입니다. 이 방법은 결코 오류를로드하지 않습니다. 귀하의 유스 케이스는 전체 객체를 메모리에로드하고 어쨌든 삭제할 수 있음을 의미합니다.

관련 문제