NSFetchedResultsController 没有调用 didChangeObject

Posted

技术标签:

【中文标题】NSFetchedResultsController 没有调用 didChangeObject【英文标题】:NSFetchedResultsController not calling didChangeObject 【发布时间】:2015-11-24 02:27:16 【问题描述】:

首先我应该说,当我直接从 xcode 将调试版本部署到我的设备时,这一切都很好。我只在构建签名版本 IPA 时才看到这个问题。

我有以下获取的结果控制器:

self.fetchedResultsController = [MyEntity MR_fetchAllSortedBy:@"date"
                                                       ascending:NO
                                                   withPredicate:[NSPredicate predicateWithFormat:@"sync == YES"]
                                                         groupBy:nil
                                                        delegate:self
                                                       inContext:[NSManagedObjectContext MR_defaultContext]];

然后实现委托方法:

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id) anObject atIndexPath:(NSIndexPath *) indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *) newIndexPath 
    switch(type) 
        case NSFetchedResultsChangeInsert: 
            NSLog(@"something was inserted");
            break;
        
        case NSFetchedResultsChangeDelete:
            break;
        case NSFetchedResultsChangeUpdate: 
            NSLog(@"something was updated");
            break;
        
        case NSFetchedResultsChangeMove:
            break;
    

这是我创建新对象的方法:

// create the new context
self.managedObjectContext = [NSManagedObjectContext MR_newMainQueueContext];

// setup default managed object context as parent
self.managedObjectContext.parentContext = [NSManagedObjectContext MR_defaultContext];

// Create new object
MyEntity *entity = [MyEntity MR_createEntityInContext:self.mangedObjectContext];

// set some properties
entity.sync = YES;  // important one, should be picked up my FRC
...

// save it
[self.managedObjectContext MR_saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) 
    NSLog(@"saved the entity: %@", entity);
];

这在通过 xcode 部署时同样有效。因此,假设我做的一切都是正确的,发布版本是否有什么不同会导致它不起作用?发布版本中有关于 CoreData 或 MagicalRecord 的信息吗?

我被卡住了,因为在查看发布版本的日志时我没有看到 didChangeObject 触发,但在调试版本中工作得很好。想法???

【问题讨论】:

上下文太多,创建实体时也拼写错误 @Andy 这怎么会有太多的上下文?它的 2. 默认上下文,当我创建一个新实体时,我创建一个 MOC 并将其父级设置为默认上下文。如果有错别字对不起。 当您调用MR_createEntityInContext 时,您使用self.mangedObjectContext。这是笔误吗? 【参考方案1】:

我个人在使用主上下文与 MagicalRecord 的主上下文关系时遇到了死锁。这真的有道理吗?

如果您想要一个单独的主线程上下文,您可以随时将其与MR_rootSavingContext 挂钩并监听根上下文的更改,然后在NSManagedObjectContextDidSaveNotification 上手动合并它们。这正是 MagicalRecord 中 rootContext 和 defaultContext 的配置方式。

我不建议MR_mergeChangesOnMainThread,因为它在我的经验中造成了太多的死锁,并且没有得到维护者的太多关注。

当我将 MagicalRecord 与 FRC 一起使用时,我通常采用的最简单方法是使用 MR_defaultContext 在 UI 线程上显示数据并在后台 MOC 中创建/保存实体,即:

[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) 
    MyEntity *entity = [MyEntity MR_createEntityInContext:localContext];

    entity.sync = YES;
 completion:^(BOOL contextDidSave, NSError *error) 
   // check for errors
];

【讨论】:

我使用不同上下文的唯一原因是我需要一个地方来存储正在填写的数据。如果用户取消,那么我会丢弃上下文。如果他们保存,则 MR 处理将其合并回根上下文。因此,根据您的建议,您认为最好将数据放入不同的对象(而不是实体),然后在保存时将数据传输到实体? 如果你想要一个临时上下文,然后将父上下文设置为根上下文并在 NSManagedObjectContextDidSaveNotification 中合并上下文。然后,您的 FRC 也应该使用您的临时主队列上下文。这里不需要默认上下文。 非常感谢您的帮助!我将我的 FRC 附加到默认上下文,因为我不希望 FRC 拾取“临时”(未保存)实体。如果我将父级设置为根上下文而不是默认值,MagicalRecord 不会处理合并吗?一旦合并,它不会传播到默认上下文吗? 干杯! MagicalRecord 会自动将根上下文的任何更改合并到默认上下文中。但它不会为您的主队列上下文执行此操作。如果您关心外部发生的变化,您必须手动进行。

以上是关于NSFetchedResultsController 没有调用 didChangeObject的主要内容,如果未能解决你的问题,请参考以下文章

在 Core Data 应用程序中调用 performFetch 后,是不是需要手动更新表视图?