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在重新启动应用程序之前我没有看到更改。任何想法为什么?

编辑:NSLogcellForRowAtIndexPath后台线程上执行会提供正确的数据,但在主线程上执行不会。

编辑 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);
4

2 回答 2

0

即使我对您的 coreDataManager 对象一无所知,您的通知注册也是错误的。您要观察的对象是您的后台托管对象上下文journalDataMOC,而不是您的coreDataManager.

所以这应该可行,但请注意,您必须将注册移动到您的addOrUpdateEntriesQueue

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

但总而言之,您应该使用 CoreData API 来完成这项工作(就像 Engin 所说的那样),因为它更干净。因此,删除所有 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]必须使用 type 进行初始化NSMainQueueConcurrencyType。另请注意,您必须在mainContext此处或将来的某个时间保存您的更改以将更改持久保存到数据库中。

于 2013-07-16T12:29:59.007 回答
0

确保您正确使用 MOC,它们不是线程安全的,只能在创建它们的线程中使用。在这种情况下,如果您使用正确enter.managedObjectContext,则与获取结果控制器的 MOC 不同(这是在主线程中)。

这意味着后台保存不一定会传播到主线程 MOC。创建获取的结果控制器时,请确保NSManagedObjectContextDidSaveNotification通过添加观察者在主线程中进行处理。

在这里查看您的代码是我注意到的几点:

  • 您应该注册由后台 MOC 而不是主线程 MOC 抛出的保存通知。
  • 你应该initWithConcurrencyType:使用初始化你的后台 MOCNSPrivateQueueConcurrencyType
  • 一旦你使用NSPrivateQueueConcurrencyType它,最好用它performBlock:来进行更改和保存,而不是使用低级 GCD 调度方法。
于 2013-07-15T11:13:54.077 回答