为啥我的核心数据没有更新?
Posted
技术标签:
【中文标题】为啥我的核心数据没有更新?【英文标题】:Why is my core data not updating?为什么我的核心数据没有更新? 【发布时间】:2013-07-15 10:58:41 【问题描述】:我在后台线程中更新核心数据,如下所示:
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
不同的条目。在主线程上,我在cellForRowAtIndexPath
中的dataLastModified
日期执行NSLog
,并且日期不会更改为最新值。如果我关闭应用程序并再次运行它,它会更新单元格的内容并将dataLastModified
日期更改为正确的值。
它似乎正在根据需要更改数据,但我的tableview
在重新启动应用程序之前看不到更改。任何想法为什么?
编辑:在后台线程上执行 cellForRowAtIndexPath
中的 NSLog
会提供正确的数据,但在主线程上执行不会。
编辑 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);
【问题讨论】:
您是为后台线程使用子上下文还是手动创建的上下文?看起来更改没有传递到主上下文。 我正在使用手动创建的上下文。我将发布更多有关其工作原理的代码。 【参考方案1】:确保您正确使用 MOC,它们不是线程安全的,只能在创建它们的线程中使用。在这种情况下,如果您使用正确,enter.managedObjectContext
与 MOC 不同获取的结果控制器(在主线程中)。
这意味着后台保存不一定会传播到主线程 MOC。在创建获取的结果控制器时添加观察者,确保在主线程中处理 NSManagedObjectContextDidSaveNotification
。
查看您的代码,我注意到以下几点:
您应该注册由后台 MOC 而不是主线程 MOC 抛出的保存通知。 您应该使用initWithConcurrencyType:
使用NSPrivateQueueConcurrencyType
初始化您的后台MOC
使用 NSPrivateQueueConcurrencyType
后,最好使用 performBlock:
进行更改并保存,而不是使用低级 GCD 调度方法。
【讨论】:
我发布了更多代码,你能看看并确保我这样做正确吗?【参考方案2】:即使我对您的 coreDataManager 对象一无所知,您的通知注册也是错误的。您要观察的对象是您的后台托管对象上下文journalDataMOC
,而不是您的coreDataManager
。
所以这应该可行,但请注意,您必须将注册移动到您的addOrUpdateEntriesQueue
:
[notificationCenter
addObserver:[AppDelegate applicationDelegate].coreDataManager
selector:@selector(mergeChanges:)
name:NSManagedObjectContextDidSaveNotification
object:journalDataMOC];
但总而言之,您应该使用 CoreData API 来完成这项工作(就像 Engin 所说的那样),因为它更干净。所以删除所有 GCD 和通知的东西并使用这个 sn-p(未测试):
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
,以将您的更改持久保存到数据库中。
【讨论】:
以上是关于为啥我的核心数据没有更新?的主要内容,如果未能解决你的问题,请参考以下文章
核心数据 - 为啥我的 NSPredicate 没有产生正确的 SQL 查询?
为啥我的“数据”。“数据”没有使用 ChangeNotifierProvider 在 ChangeNotifier 类中更新?