我在后台线程中更新核心数据,如下所示:
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
在应用重新启动之前没有看到更改。有什么想法吗?
编辑:在后台线程上执行NSLog
中的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)
确保您正确使用MOC,它们不是线程安全的,只能在创建它们的线程中使用。在这种情况下,如果您正确执行它enter.managedObjectContext
不同于获取结果控制器的MOC(在主线程中)。
这意味着在后台保存不一定会传播到主线程MOC。确保在创建获取结果控制器时通过添加观察者来处理主线程中的NSManagedObjectContextDidSaveNotification
。
在这里查看您的代码是我注意到的几点:
initWithConcurrencyType:
NSPrivateQueueConcurrencyType
初始化您的背景MOC
NSPrivateQueueConcurrencyType
后,最好使用performBlock:
进行更改并保存,而不是使用低级GCD调度方法。答案 1 :(得分: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
保存时,它会将更改“推送”到paren上下文(mainContext
)。
请注意,您的[[[AppDelegate applicationDelegate] coreDataManager] managedObjectContext]
必须使用NSMainQueueConcurrencyType
类型进行初始化。另请注意,您必须在此处或在将来的某个时间保存mainContext
,以便将更改保留到数据库中。