保持 CoreData NSManagedObject 新鲜

Posted

技术标签:

【中文标题】保持 CoreData NSManagedObject 新鲜【英文标题】:Keeping a CoreData NSManagedObject fresh 【发布时间】:2014-01-18 19:47:43 【问题描述】:

想象一下像 Instagram 这样的社交照片应用。您在动态中看到您朋友的一张照片。该照片以如下方式保存在 CoreData 中:

Photo (NSManagedObject)
 Attributes: id, imageURL
 Relationships: comments (set of Comment objects), likes (set of Like objects)

我有一个引用 Photo 对象的视图控制器。此视图控制器还处理喜欢和评论照片的操作。

因此,当有人喜欢一张照片时,流程是这样的:将喜欢的内容发送到服务器。如果 API 发布成功,则使用从服务器接收到的任何新信息更新 CoreData 中的 Photo 对象,其中将包括新的点赞。此时,CoreData 中的 Photo 应该比我按下 Like 按钮之前多了一个与之相关的 Like 对象。

现在我遇到了问题。视图控制器需要更新照片上的点赞数。在成功块中,我正在这样做:

  self.likesLabel.text = [NSString stringWithFormat:@"%d likes", self.photo.likes.count];

问题在于 self.photo.likes.count 此时报告为 0(在我按下“赞”按钮之前它不是零)。如果我在其他地方导航并返回此屏幕,计数将正确更新。因此,当我更新 Photo managedObject 时,它似乎变得“脏”了。更新可能发生在另一个上下文中(我使用 Magical Record)。更新看起来像这样:

NSManagedObjectContext* context = [NSManagedObjectContext MR_contextForCurrentThread];
Photo* photo = [Photo MR_findFirstWithPredicate:somePredicate inContext:context];
...
photo.likes = likes;
photo.comments = comments;
[photo save:context];

所以问题是,如何在视图控制器中正确更新 Photo 对象,以便始终可靠地查询喜欢和 cmets 的数量?一般来说,如果 NSMangagedObject 可能在其他线程/上下文中更新,您如何始终保持新版本?

我尝试监听 NSManagedObjectContextObjectsDidChangeNotification,但我遇到了同样的问题,当我收到通知时照片报告 0 个喜欢和 cmets。

【问题讨论】:

正在获取 != 也刷新了 BTW 【参考方案1】:

我经常使用的一种解决方案是 KVO。在您的情况下,我会观察托管对象上的“喜欢”属性。您可以查找有关如何正确执行此操作的标准 KVO 文章。然而,这只是故事的一半。因此,为了使这些值正确地为您更改,“管理”该属性的 NSManagedObjectContext 需要自行更新。这是在线程隔离上下文的情况下合并保存 NSManagedOjbectContextDidSaveNotification 事件或父/子合并规则发挥作用的地方。关键是,您可以在应用程序内的任何上下文中对实际数据进行更改。您可以将这些更改合并到您当前关心的上下文中(可能是屏幕上显示的内容)。

话虽如此,MagicalRecord 应该有一些内置方法已经为您处理了一半的问题。如果没有,请确保在保存背景上下文时正确更新显示使用信息的上下文。需要记住的是,您必须更新上下文,一旦上下文合并到更新时的新更改中,您的 KVO 方法就会以正确的值触发。

【讨论】:

【参考方案2】:

侦听并应用在其他上下文中进行的合并

#pragma mark - Core Data stack

- (void)mergeChanges:(NSNotification *)notification 
    // Merge changes into the main context on the main thread
    dispatch_async(dispatch_get_main_queue(), ^
        [self.mainManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];
        [[NSNotificationCenter defaultCenter] postNotificationName:MyMainContextMergedChangesNotification object:nil];
    );

合并后可以刷新界面


或者/另外,您可以强制上下文从调用 refreshObject: 的数据库中刷新对象

【讨论】:

获取不会刷新上下文自己的缓存! 感谢您的建议。我刚试过这个。我确实收到了通知。即使在调用 [self.photo.managedObjectContext mergeChangesFromContextDidSaveNotification:notification]; 之后,self.photo.likes.count 仍然为零 奇怪 - 请注意合并是异步的(!) 也试过这个:[self.photo.managedObjectContext refreshObject:self.photo mergeChanges:YES]; 妈妈,那么它似乎是真实的 0 ;D 对不起 - 没有线索

以上是关于保持 CoreData NSManagedObject 新鲜的主要内容,如果未能解决你的问题,请参考以下文章

使用 RestKit 0.2 从 CoreData 获取本地数据

保持 CoreData NSManagedObject 新鲜

所有实例属性的核心数据总和

RestKit + CoreData:操作成功时替换实体内容,失败时保持原样

我使用 coreData 保存数据,但对象保持为零

将 NSManagedObject 保持在 CoreData NSManagedObjectContext 块之外