ios – NSFetchResultsController显示虚假对象

ios – NSFetchResultsController显示虚假对象,第1张

概述我有一个UITableView,通过NSFetchResultController显示从WebServer接收的Core Data实体中的对象.用户可以修改它们并将它们发送回服务器.她还可以点击按钮从服务器刷新这些对象. 每个对象都有一个标识符属性.当我从服务器收到对象JSON时,我会查找具有相同标识符的现有对象.它存在,我更新它.否则我创造它. 其中一些是在主队列NSManagedObjectC 我有一个UItableVIEw,通过NSFetchResultController显示从WebServer接收的Core Data实体中的对象.用户可以修改它们并将它们发送回服务器.她还可以点击按钮从服务器刷新这些对象.

每个对象都有一个标识符属性.当我从服务器收到对象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显示虚假对象所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1048065.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存