1

현재 CoreData와 NSFectchedResultsController를 사용하는 응용 프로그램을 개발 중입니다. 이 응용 프로그램은 NSFetchedResultsController를 사용하는 하나의 UITableView 만 포함합니다.NSFetchedResultsController/CoreData with multiple threads issue

1/ 응용 프로그램이 시작되면 다른 스레드가 분리됩니다. 이 새로운 스레드에서 WS 호출은 웹 서버에서 데이터를 검색하도록 허용합니다. WS 호출 후 다른 NSManagedObjectContext (다른 스레드 => 다른 컨텍스트)와 함께 CoreData DB에 데이터를 저장합니다. 새로운 개체를 저장하기 전에이 개체의 모든 개체를 삭제해야합니다. mergeChangesFromContextDidSaveNotification을 통해이 컨텍스트를 주 컨텍스트와 병합합니다. 응용 프로그램이 실행될 때 다음과 같은 오류가있어

 // UIView 
    - (NSFetchedResultsController*) offersFRC { 

     if (offersFRC == nil) 
     { 
      NSManagedObjectContext *l_ManagedObjectContext = [[DataManager sharedDataManager] getContext]; 

      NSFetchRequest *l_FetchRequest = [[NSFetchRequest alloc] init]; 

      NSEntityDescription *l_Entity = [NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:l_ManagedObjectContext]; 
      [l_FetchRequest setEntity:l_Entity]; 

      [l_FetchRequest setFetchBatchSize:5]; 

      NSNumber *sortType = [self.searchCriterions objectForKey:@"sortType"]; 
      NSSortDescriptor *l_SortDescriptor = [[NSSortDescriptor alloc] initWithKey:[Constants getFieldNameBySortType:sortType] ascending:[Constants isAscendingBySortType:sortType]]; 
      [l_FetchRequest setSortDescriptors:[NSArray arrayWithObjects:l_SortDescriptor, nil]]; 
      [l_SortDescriptor release]; 

      NSFetchedResultsController *l_FetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:l_FetchRequest                          managedObjectContext:l_ManagedObjectContext 
       sectionNameKeyPath:nil                          
       cacheName:nil]; 
      [l_FetchRequest release]; 

      [self setOffersFRC:l_FetchedResultsController]; 
      [l_FetchedResultsController release],l_FetchedResultsController = nil; 

      [self.offersFRC setDelegate:self]; 
     } 

     return offersFRC; 
    } 

3/ : 중요

 2012-02-29 11:56:09.119 Nanopost[1996:207] *** Terminating app due to uncaught exception  'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault for '0x5c3c760 <x-coredata://E176B0A1-275B-4332-9231-49FD88238C2B/Ads/p231>'' 
    *** Call stack at first throw: 
    (
    0 CoreFoundation      0x02bfe919 __exceptionPreprocess + 185 
    1 libobjc.A.dylib      0x02e595de objc_exception_throw + 47 
    2 CoreData       0x028b833f _PFFaultHandlerLookupRow + 1407 
    3 CoreData       0x028b5ee3 _PF_FulfillDeferredFault + 499 
    4 CoreData       0x028b9f3f _sharedIMPL_pvfk_core + 95 
    5 CoreData       0x0292a010 _PF_Handler_Public_GetProperty + 160 
    6 Foundation       0x02442c4f -[NSSortDescriptor compareObject:toObject:] + 128 
    7 CoreData       0x0297db5e +[NSFetchedResultsController(PrivateMethods) _insertIndexForObject:inArray:lowIdx:highIdx:sortDescriptors:] + 286 
    8 CoreData       0x0297e1b2 -[NSFetchedResultsController(PrivateMethods) _postprocessInsertedObjects:] + 402 
    9 CoreData       0x029841bc -[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:] + 1804 
    10 Foundation       0x02380c1d _nsnote_callback + 145 
    11 CoreFoundation      0x02bd6cf9 __CFXNotificationPost_old + 745 
    12 CoreFoundation      0x02b5611a _CFXNotificationPostNotification + 186 
    13 Foundation       0x023767c2 -[NSNotificationCenter postNotificationName:object:userInfo:] + 134 
    14 CoreData       0x028c0519 -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] + 89 
    15 CoreData       0x028f802b -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:] + 1579 
    16 Foundation       0x02395e9a __NSThreadPerformPerform + 251 
    17 CoreFoundation      0x02bdfd7f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15 
    18 CoreFoundation      0x02b3e2cb __CFRunLoopDoSources0 + 571 
    19 CoreFoundation      0x02b3d7c6 __CFRunLoopRun + 470 
    20 CoreFoundation      0x02b3d280 CFRunLoopRunSpecific + 208 
    21 CoreFoundation      0x02b3d1a1 CFRunLoopRunInMode + 97 
    22 GraphicsServices     0x031e62c8 GSEventRunModal + 217 
    23 GraphicsServices     0x031e638d GSEventRun + 115 
    24 UIKit        0x0063cb58 UIApplicationMain + 1160 
    25 Nanopost       0x0000230a main + 170 
    26 Nanopost       0x00002255 start + 53 
    ) 
    terminate called after throwing an instance of '_NSCoreDataException' 

여기

2/

 // Data Manager (in another thread) 
     NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init]; 
     [[NSNotificationCenter defaultCenter] addObserver:self 
               selector:@selector(contextDidSave:) 
               name:NSManagedObjectContextDidSaveNotification 
               object:context]; 
     [context setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy]; 
     [context setPersistentStoreCoordinator:[self getPersistentStoreCoordinator]]; 

     ... 

     for (NSManagedObject * obj in objects) 
     { 
      [context deleteObject:obj]; 
     } 

     ... 

     for(NSDictionary *serverObj in serverObjects) 
     { 
      objAd = [NSEntityDescription 
         insertNewObjectForEntityForName:@"MyEntity" 
         inManagedObjectContext:context]; 
      ... 
     } 

     [context save:&error]; 

     [[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:context]; 
     [context release]; 

     ... 

     - (void)contextDidSave:(NSNotification *)notification 
     { 

      SEL selector = @selector(mergeChangesFromContextDidSaveNotification:); 
      [[self getContext] performSelectorOnMainThread:selector withObject:notification waitUntilDone:YES]; 
     } 

     - (NSManagedObjectContext *) getContext 
     { 
      return [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; 
     } 

     - (NSPersistentStoreCoordinator *) getPersistentStoreCoordinator 
     { 
      return [(AppDelegate *)[[UIApplication sharedApplication] delegate] persistentStoreCoordinator]; 
     } 
내 NSFectchedResultsController의 게터입니다 메모
:

그것은 단지 iOS4에 충돌
  • controllerWillChangeContent는 응용 프로그램의 충돌 전에 내 코드에서 마지막으로 호출 된 함수입니다. controllerDidChangeContent/didChangeObject/didChangeSection이 호출되지 않습니다.
  • 내가 언급
  • [l_FetchRequest setFetchBatchSize : 5] => 더 이상 충돌하지
  • 나는 [저장 컨텍스트 : & 오류] 추가
  • 삽입 => 더 이상 충돌 개체를 삭제 한 후 새로운 객체 이전을
  • 내가 사용하는 [25 l_FetchRequest setFetchBatchSize] => 더 이상 충돌

나는이 문제를 이해하려고 많은 시간을 보냈습니다 그래서 당신에게 매우 감사드립니다 내가 사용하는 경우 : [l_FetchRequest setFetchBatchSize 24] =이>

  • 을 충돌 당신의 대답을 위해 전진하십시오!

    토마스

    편집 1 (@Jody) : 안녕 조디와 귀하의 답변을 주셔서 대단히 감사합니다! 여기

    는 contextDidSave을 처리하는 데 사용하는 코드입니다 :

    - (void)contextDidSave:(NSNotification *)notification 
        { 
         SEL selector = @selector(mergeChangesFromContextDidSaveNotification:); 
         [[self getContext] performSelectorOnMainThread:selector withObject:notification waitUntilDone:YES]; 
        } 
    

    "먼저 나에게 당신이 사용하고있는 상황에 대한 자세한 얘기를 해"

    나는이 응용 프로그램에서이 컨텍스트를 사용

    • N ° 1 : XCodeProject를 만들 때 AppDelegate에서 기본적으로 만들어집니다. 이 컨텍스트는 FRC에서 사용하며 UITableView의 행을 표시 할 수 있습니다.

    • N ° 2 : 내 DB (WS 호출, 삭제, 다시 삽입, 저장) 새로 고침을 허용하는 싱글 톤 인 "DataManager"(내 게시물의 첫 번째 코드 블록)에 작성되었습니다.

    컨텍스트 번호 2가 저장되면이 컨텍스트를 주 컨텍스트 (컨텍스트 N ° 1)와 병합하기 위해 contextDidSave가 호출됩니다. 그 후, 내 FRC 대리인의 메서드 "controllerWillChangeContent"가 호출됩니다. 나는이 메소드에 포함 된 코드를 표시하는 데 도움이되지 않을 것이라고 생각한다. NSLog를 넣었을지라도이 메소드 (NSLog를 많이 넣었고 controllerWillChangeContent에 포함 된 NSLog가 전에 표시되는 마지막 값이다. 충돌).

    나는 애플 개발자 포럼에 게시하고 흥미로운 응답이 : https://devforums.apple.com/thread/152172?tstart=0

    편집 2 (@Jody) : 안녕 조디!

    다음과 같은 방법에서 볼 수 있듯이, 내 FRC는 다른 스레드에서 MOC를 사용하지 않습니다

    - (NSManagedObjectContext *) getContext 
        { 
         return [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; 
        } 
    

    내 "DataManager에"이 방법은 AppDelegate에의 MOC (= 메인 스레드의 MOC)를 반환

  • 답변

    0

    데이터베이스에서 하나의 컨텍스트로 삭제하므로 다른 컨텍스트를 적절하게 새로 고쳐야하며, 특히 삭제 된 데이터에 대한 개체 참조를 제거해야합니다.

    contextDidSave를 처리하기위한 코드는 무엇입니까? 또한 FRC 대리인이 데이터 업데이트 알림을 사용하여 수행하는 작업은 무엇입니까?

    EDIT 당신이 당신의 관리 객체 컨텍스트를 혼합하는 것 같습니다

    . 당신은 ...

    // Data Manager (in another thread) 
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init]; 
    

    을로드하고 데이터베이스를 수정하기 위해 데이터 관리자에서 하나를 사용하고 그리고 알림을 통해 응용 프로그램으로 데이터를 끌어 "기본"MOC를 사용하여, 아직 당신 가져온 결과처럼 보인다 그것은 아마뿐만 아니라 (앱 위임에서) 주요 MOC를 사용한다

    NSManagedObjectContext *l_ManagedObjectContext = [[DataManager sharedDataManager] getContext]; 
    

    컨트롤러는 ... 다른 스레드에서 MOC를 사용하려고합니다.

    +0

    서식에 형식이 없으므로 주석에 코드를 넣지 마십시오. 또한 더 나은 질문을 제공하기 위해 질문을 편집하는 것이 좋습니다. 코드에 관해서는, DidSave 핸들링을 다루기 전에 먼저 사용중인 컨텍스트에 대해 더 자세히 말해야합니다 ... 다시 어디에서 왔는지? 어떻게 만들어 졌습니까? MR 문맥과의 관계는 무엇입니까? –

    +0

    죄송합니다. 같은 질문이지만 MR 파트를 무시합니다 (Hardees의 도로에서 응답). 다른 질문과 섞였습니다. 혼동을해서 죄송합니다. –

    +0

    Jody에게 감사드립니다! 내 질문을 편집했습니다! –