我的应用程序正在使用绑定到Core Data存储的NSFetchedResultsController,它到目前为止运行良好,但我现在正试图使更新代码异步,我遇到了问题。我创建了一个NSOperation子类来进行更新,并成功将这个新对象添加到NSOperationQueue中。更新代码正在按照我的预期执行,我已通过调试日志和运行后检查SQLite存储来验证这一点。
问题是我的后台操作完成后,新的(或更新的)项目不会出现在我的UITableView中。基于我有限的理解,我认为我需要通知主要的managedObjectContext发生了更改,以便它们可以合并。我的通知是触发,坚果没有新项目出现在tableview中。如果我停止应用程序并重新启动它,对象将出现在tableview中,这使我相信它们已成功插入到核心数据存储中,但未被合并到主线程上使用的managedObjectContext中。
我已经包含了我的操作的init,main和notification方法的示例。我错过了一些重要的事情,或者可能以错误的方式解决这个问题吗?任何帮助将不胜感激。
- (id)initWithDelegate:(AppDelegate *)theDelegate
{
if (!(self = [super init])) return nil;
delegate = theDelegate;
return self;
}
- (void)main
{
[self setUpdateContext:[self managedObjectContext]];
NSManagedObjectContext *mainMOC = [self newContextToMainStore];
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self
selector:@selector(contextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:updateContext];
[self setMainContext:mainMOC];
// Create/update objects with mainContext.
NSError *error = nil;
if (![[self mainContext] save:&error]) {
DLog(@"Error saving event to CoreData store");
}
DLog(@"Core Data context saved");
}
- (void)contextDidSave:(NSNotification*)notification
{
DLog(@"Notification fired.");
SEL selector = @selector(mergeChangesFromContextDidSaveNotification:);
[[delegate managedObjectContext] performSelectorOnMainThread:selector
withObject:notification
waitUntilDone:YES];
}
在调试时,我检查了notification
中发送的contextDidSave:
对象,它似乎包含了所有已添加的项目(摘录如下)。这继续让我认为插入/更新正确发生,但不知何故合并没有被解雇。
NSConcreteNotification 0x6b7b0b0 {name = NSManagingContextDidSaveChangesNotification; object = <NSManagedObjectContext: 0x5e8ab30>; userInfo = {
inserted = "{(\n <GCTeam: 0x6b77290> (entity: GCTeam; id: 0xdc5ea10 <x-coredata://F4091BAE-4B47-4F3A-A008-B6A35D7AB196/GCTeam/p1> ; data: {\n changed =
答案 0 :(得分:0)
接收通知的方法必须确实通知您的上下文,您可以尝试这样的事情,这就是我在我的应用程序中所做的事情:
- (void)updateTable:(NSNotification *)saveNotification
{
if (fetchedResultsController == nil)
{
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
//Update to handle the error appropriately.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
exit(-1); // Fail
}
}
else
{
NSManagedObjectContext *context = [fetchedResultsController managedObjectContext];
// Merging changes causes the fetched results controller to update its results
[context mergeChangesFromContextDidSaveNotification:saveNotification];
// Reload your table view data
[self.tableView reloadData];
}
}
希望有所帮助。
答案 1 :(得分:0)
根据您所做的具体情况,您可能会采取错误的方式。
对于大多数情况,您只需使用NSFetchedResultsControllerDelegate分配代理即可。您根据需要为“respondToChanges”中指定的方法之一提供实现,然后向tableView发送reloadData消息。
答案 2 :(得分:0)
答案结果与发布的代码无关,最终按照我的预期运作。由于我仍然不完全确定的原因,它与应用程序的首次启动有关。当我在创建Core Data存储后尝试在启动时运行更新操作时,它按预期工作。我通过在应用程序中预加载一个版本的sqlite数据库来解决这个问题,这样它就不需要在首次启动时创建一个空商店。我希望我理解为什么这解决了这个问题,但我正计划这样做。我要离开这里,希望别人可能觉得它很有用,而且不会像我这样浪费那么多时间。
答案 3 :(得分:0)
我在模拟器中遇到了类似的问题。从根表转换到选定文件夹时,我正在开始更新过程。更新过程将从Web服务器更新CoreData,保存,然后合并,但数据未显示。如果我来回浏览几次它最终会出现,而曾经它像发条一样工作(但我从来没有能够重复完美的运行)。这给了我一个想法,也许这是模拟器中的线程/事件计时问题,其中表刷新太快或通知只是没有正确排队或沿着这些线排队。我决定尝试在Instruments中运行,看看我是否可以查明问题(所有CoreData,CPU Monitor,Leaks,Allocations,Thread States,Dispatch等等)。从那时起,我每次都做了一次空白的“第一次运行”,它完美地运作了。也许仪器正在放慢速度吗?
最终我需要在设备上进行测试以获得准确的测试,如果问题仍然存在,我将在接受的答案中尝试您的解决方案(创建一个基本的sql-lite数据库来加载)。