2013-07-15 1 views
1

그래서 같이 백그라운드 스레드에서 핵심 데이터를 업데이트 :핵심 데이터가 업데이트되지 않는 이유는 무엇입니까?

의 tableview의 각 셀에
entry.message = [self contentForNoteWithEDML:note.content]; 
entry.dataLastModified = [NSDate date]; 
[entry.managedObjectContext save:nil]; 

dispatch_async(dispatch_get_main_queue(), ^{ 
    NSError *error; 

    if (![[self fetchedResultsController] performFetch:&error]) { 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    } 

    [self.tableView reloadData]; 
}); 

, 그것은 fetchedResultsController에서 다른 항목을 표시합니다. 주 스레드에서 dataLastModified 날짜의 을 cellForRowAtIndexPath에두고 날짜가 가장 최근 값으로 변경되지 않습니다. 앱을 닫고 다시 실행하면 셀 내용이 업데이트되고 dataLastModified 날짜가 올바른 값으로 변경됩니다.

필요에 따라 데이터가 변경되는 것 같지만 앱이 다시 시작될 때까지 내 tableview에 변경 사항이 표시되지 않습니다. 어떤 아이디어?

편집 : 배경 스레드에서 을 cellForRowAtIndexPath에서 수행하면 올바른 데이터를 얻을 수 있지만 주 스레드에서 수행하는 것은 아닙니다.

편집 2 : 내 배경 컨텍스트 작동 방법 :

NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 

[notificationCenter 
    addObserver:[AppDelegate applicationDelegate].coreDataManager 
    selector:@selector(mergeChanges:) 
    name:NSManagedObjectContextDidSaveNotification 
    object:[AppDelegate applicationDelegate].coreDataManager.managedObjectContext]; 
NSPersistentStoreCoordinator *journalDataPSC = [AppDelegate applicationDelegate].coreDataManager.managedObjectContext.persistentStoreCoordinator; 

dispatch_queue_t addOrUpdateEntriesQueue = dispatch_queue_create("com.App.AddOrUpdateEntries", NULL); 
dispatch_async(addOrUpdateEntriesQueue, ^{ 

    NSManagedObjectContext *journalDataMOC = [[NSManagedObjectContext alloc] init]; 
    [journalDataMOC setPersistentStoreCoordinator:journalDataPSC]; 

    //Some code to get me an entry on this context 
    entry.message = [self contentForNoteWithEDML:note.content]; 
    entry.dataLastModified = [NSDate date]; 
    [entry.managedObjectContext save:nil]; 

    [[NSNotificationCenter defaultCenter] removeObserver:[AppDelegate applicationDelegate].coreDataManager]; 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     NSError *error; 

     if (![[self fetchedResultsController] performFetch:&error]) { 
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     } 

     [self.tableView reloadData]; 
    }); 
}); 
dispatch_release(addOrUpdateEntriesQueue); 
+0

백그라운드 스레드 또는 수동 생성 된 컨텍스트에 하위 컨텍스트를 사용하고 있습니까? 변경 사항이 주 컨텍스트로 전달되지 않는 것처럼 보입니다. –

+0

수동으로 생성 된 컨텍스트를 사용하고 있습니다. 이 코드가 작동하는 방법에 대한 코드를 더 게시 할 것입니다. – Andrew

답변

0

당신은 MOC의 제대로, 그들이있는 것은 아닙니다 안전 스레드 만 그들이에서 만든 스레드에서 사용할 수있는이 사용하고 있는지 확인합니다.을 당신이 그것을 제대로하고 있다면, enter.managedObjectContext은 (메인 쓰레드에있는) 페치 된 결과 컨트롤러의 MOC와 다르다.

즉, 백그라운드에서의 저장이 반드시 주 스레드 MOC로 전파되지는 않는다는 의미입니다. 페치 된 결과 컨트롤러를 만들 때 옵저버를 추가하여 주 스레드에서 NSManagedObjectContextDidSaveNotification을 처리해야합니다.

  • 당신은 배경 MOC하지 메인 스레드의 MOC에 의해 슬로우 저장 통지를 등록해야합니다 :

    코드를 보면 여기에 내가 발견 몇 가지 포인트가 있습니다.

  • 당신은 당신이 당신을 변경하고 대신 낮은 수준의 GCD 파견 방법을 사용하는 저장 performBlock:를 사용하는 것이 훨씬 낫다 NSPrivateQueueConcurrencyType를 사용하면
  • NSPrivateQueueConcurrencyType를 사용 initWithConcurrencyType:와 배경 MOC를 초기화해야한다.
+0

좀 더 코드를 게시했습니다. 한 번 둘러보고 제대로하고 있는지 확인하십시오. – Andrew

+0

답변을 업데이트했습니다. 도움이되기를 바랍니다. –

0

coreDataManager 객체에 대해 알지 못하더라도 알림 등록이 잘못되었습니다. 관찰하려는 개체는 coreDataManager이 아니라 백그라운드 관리 개체 컨텍스트 journalDataMOC입니다.

그래서이 작동하지만 당신은 당신의 addOrUpdateEntriesQueue 내부의 등록을 이동해야 통지해야합니다

[notificationCenter 
    addObserver:[AppDelegate applicationDelegate].coreDataManager 
    selector:@selector(mergeChanges:) 
    name:NSManagedObjectContextDidSaveNotification 
    object:journalDataMOC]; 

을하지만 전부는 지점을 인식 말한 것처럼 (이 작업을 수행 할 CoreData API를 사용한다) 그것은 훨씬 깨끗합니다. 그래서 모든 GCD 및 알림 물건을 제거하고이 조각을 (을 테스트하지)를 사용 :

NSManagedObjectContext *mainContext = [[[AppDelegate applicationDelegate] coreDataManager] managedObjectContext]; 
NSManagedObjectContext *journalDataMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
[journalDataMOC setParentContext:mainContext]; 

[journaDataMOC performBlock:^{ 

    //Some code to get me an entry on this context 
    entry.message = [self contentForNoteWithEDML:note.content]; 
    entry.dataLastModified = [NSDate date]; 

    [journalDataMOC save:nil]; 

    [NSOperationQueue mainQueue] addOperationWithBlock:^{ 

     NSError *error; 
     [mainContext save:&error]; 

     if (![[self fetchedResultsController] performFetch:&error]) { 
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     } 

     [self.tableView reloadData];  
    }]; 
}]; 
journalDataMOC는 괄호 컨텍스트 ( mainContext)에 것이다 "푸시"변경 사항을 저장

.

[[[AppDelegate applicationDelegate] coreDataManager] managedObjectContext]NSMainQueueConcurrencyType으로 초기화해야합니다. 또한 변경 내용을 데이터베이스에 유지하려면 mainContext을 여기 또는 나중에 저장해야합니다.