每个对象都有一个标识符属性.当我从服务器收到对象JSON时,我会查找具有相同标识符的现有对象.它存在,我更新它.否则我创造它.
其中一些是在主队列NSManagedobjectContext中发生的,其中一些在子私有队列中.在所有情况下,它都发生在performBlock方法中,并保存子上下文及其父上下文.
这听起来像面包和黄油核心数据模式.现在我的问题:
有时,在服务器刷新之后,NSFetchResultController会显示同一对象的两个实例.这两个副本是不同的(它们的指针是不同的).一个副本完成,另一个副本只设置其属性值,而不是其关系.两者都具有相同的NSManagedobjectContext.两者都具有相同的标识符.
我该如何调试这样的问题?我检查了我的CoreData存储没有相同对象的两个实例(通过查看sqlite文件,并在awakeFromInsert上放置一个符号断点).我查找了查找现有实例的代码,它发现它没问题.
在这一点上,我陷入困境,我很难想象一个调试策略.
我可以提供所有可以想象的细节,但除了显示完整的源代码之外,我不确定什么是最有用的.
谢谢你的帮助.
JD
编辑1:这是我的控制器:dIDChangeObject:atIndexPath:forChangeType:newIndexPath:
- (voID)controller:(NSFetchedResultsController *)controller dIDChangeObject:(ID)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath{ UItableVIEw *tableVIEw = self.tableVIEw; switch(type) { case NSFetchedResultsChangeInsert: [tableVIEw insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UItableVIEwRowAnimationFade]; break; case NSFetchedResultsChangeDelete: [tableVIEw deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UItableVIEwRowAnimationFade]; break; case NSFetchedResultsChangeUpdate: [self configureCell:(DaySlotCell*)[tableVIEw cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; break; case NSFetchedResultsChangeMove: [tableVIEw deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UItableVIEwRowAnimationFade]; [tableVIEw insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UItableVIEwRowAnimationFade]; break; }}
编辑2:这是我的上下文排列方式.我有一个中央单例模型对象,负责与远程服务器的通信(因此它的类名sgiServer).它有两个背景:
> mainManagedobjectContext,一个NSMainQueueConcurrencyType,用于所有与UI相关的东西,包括上面描述的NSFetchResultController(尽管我在网上读到NSFetchResultController可以使用私有上下文).它与持久性存储无关.这是一个孩子:
> persistentManagedobjectContext,一个与持久性商店关联的nsprivateQueueConcurrencyType,负责在后台保存到商店:
它们是在发布时创建的,如下所示:
NSManagedobjectContext *managedobjectContext = [[NSManagedobjectContext alloc] initWithConcurrencyType:nsprivateQueueConcurrencyType];managedobjectContext.persistentStoreCoordinator = persistentStoreCoordinator;self.persistentManagedobjectContext = managedobjectContext;managedobjectContext = [[NSManagedobjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];managedobjectContext.parentContext = self.persistentManagedobjectContext;self.mainManagedobjectContext = managedobjectContext;
需要上下文的代码以两种不同的方式执行,具体取决于它们是否需要主上下文:
NSManagedobjectContext *moc = [server mainManagedobjectContext];
要么
NSManagedobjectContext *moc = [server newPrivateContext];
其中newPrivateContext只是创建一个新的nsprivateQueueConcurrencyType上下文,主要的子项:
- (NSManagedobjectContext *) newPrivateContext{ NSManagedobjectContext *privateContext = [[NSManagedobjectContext alloc] initWithConcurrencyType:nsprivateQueueConcurrencyType]; privateContext.parentContext = self.mainManagedobjectContext; return privateContext;}
最后,我定义了两个保存方法,一个是同步的,另一个是异步的:
- (voID)syncSaveContext: (NSManagedobjectContext *) moc persisting:(BOol)savetodisk{ NSManagedobjectContext *mainContext = self.mainManagedobjectContext; if (moc && moc != mainContext) { NSError *error = nil; if (![moc save:&error]) { NSLog(@"Error saving MOC: %@\n%@",[error localizedDescription],[error userInfo]); } } if (mainContext && [mainContext hasChanges]) { [mainContext performBlockAnDWait:^{ NSError *error = nil; if (![mainContext save:&error]) { NSLog(@"Error saving MOC: %@\n%@",[error userInfo]); } }]; } if (savetodisk) { NSManagedobjectContext *privateContext = self.persistentManagedobjectContext; if (privateContext && [privateContext hasChanges]) { [privateContext performBlockAnDWait: ^{ NSError *error = nil; if (![privateContext save:&error]) { NSLog(@"Error saving private MOC: %@\n%@",[error userInfo]); } }]; } }}
和:
- (voID)asyncSaveContext: (NSManagedobjectContext *) moc persisting:(BOol)savetodisk{ NSManagedobjectContext *mainContext = self.mainManagedobjectContext; if (moc && moc != mainContext) { NSError *error = nil; if (![moc save:&error]) { NSLog(@"Error saving MOC: %@\n%@",[error userInfo]); } } if (mainContext && [mainContext hasChanges]) { [mainContext performBlock:^{ NSError *error = nil; if ([mainContext save:&error]) { if (savetodisk) { NSManagedobjectContext *privateContext = self.persistentManagedobjectContext; if (privateContext && [privateContext hasChanges]) { [privateContext performBlock: ^{ NSError *error = nil; if (![privateContext save:&error]) { NSLog(@"Error saving private MOC: %@\n%@",[error userInfo]); } }]; } } } else { NSLog(@"Error saving MOC: %@\n%@",[error userInfo]); } }]; }}
异步的是最常用的,通常在任何用户触发的 *** 作结束时.
当我想确保在继续之前完成保存时,偶尔会使用同步一个.
在调用save的地方,尝试在父上下文中调用obtainPermanentIDsForObjects执行块,如下所示:
[self.parentContext performBlockAnDWait:^{ NSError * error = nil; [self.parentContext obtainPermanentIDsForObjects:[self.parentContext.insertedobjects allObjects] error:&error]; [self.parentContext save: &error] }];总结
以上是内存溢出为你收集整理的ios – NSFetchResultsController显示虚假对象全部内容,希望文章能够帮你解决ios – NSFetchResultsController显示虚假对象所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)