2013-07-15 3 views
1

обновляет основные данные в фоновом потоке, например, так:Почему мои основные данные не обновляются?

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]; 
}); 

На каждой клетку Tableview, он отображает другую запись из fetchedResultsController. В основном потоке я делаю NSLog в cellForRowAtIndexPath по дате dataLastModified, и дата не изменяется до последнего значения. Если я закрою приложение и запустил его снова, он обновит содержимое ячейки, а значение даты dataLastModified изменится на правильное значение.

Похоже, что данные изменяются, если требуется, но мой tableview не видит изменений до тех пор, пока приложение не будет перезапущено. Любые идеи почему?

EDIT: Выполнение NSLog в cellForRowAtIndexPath на фоновом потоке дает правильные данные, но делать это на основной теме нет.

EDIT 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.
  • Вы должны инициализировать фон MOC с initWithConcurrencyType: использованием NSPrivateQueueConcurrencyType
  • После того, как вы используете NSPrivateQueueConcurrencyType это гораздо лучше использовать performBlock:, чтобы сделать изменения и сохранить вместо использования методов НОДОВ отправки низкого уровня.
+0

Я отправил еще какой-нибудь код, не могли бы вы взглянуть и убедиться, что я делаю это правильно? – Andrew

+0

Я обновил ответ. Надеюсь, поможет. –

0

Несмотря на то что я ничего не знаю о вашем объекте coreDataManager, ваша регистрация регистрации неверна. Объект, который вы хотите наблюдать, - это фоновый контекст управляемого объекта journalDataMOC, а не ваш coreDataManager.

Так это должно работать, но обратите внимание, что вы должны переместить регистрацию внутри addOrUpdateEntriesQueue:

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

Но в целом вы должны использовать API CoreData, чтобы сделать эту работу (как сказал Engin), поскольку он намного чище. Так удалить все НОД и уведомления вещи и использовать этот фрагмент (не тестировалось):

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 сохраняет она будет «толкать» изменения до PAREN контекста (mainContext).

Обратите внимание, что ваш [[[AppDelegate applicationDelegate] coreDataManager] managedObjectContext] должен быть инициализирован с номером NSMainQueueConcurrencyType. Также обратите внимание, что вам нужно сохранить mainContext здесь или в будущем, чтобы сохранить ваши изменения в базе данных.

Смежные вопросы