NSFetchedResultsController 未显示来自子对象的具有 nil 部分名称的新对象

Posted

技术标签:

【中文标题】NSFetchedResultsController 未显示来自子对象的具有 nil 部分名称的新对象【英文标题】:NSFetchedResultsController not showing new object with nil section name from child object 【发布时间】:2013-05-26 17:31:41 【问题描述】:

我有每个都有一个类别的项目。我使用NSFetchedResultsController 来显示项目并按类别名称将它们分组。

self.fetchedResultsController = [Item MR_fetchAllSortedBy:@"category.categoryName" ascending:YES withPredicate:nil groupBy:@"category.categoryName" delegate:self];

但是当我添加如下两个新项目时,只有一个具有类别的项目被插入到列表中。如果我重新启动应用程序,则没有类别名称的应用程序将按原样显示在没有部分的顶部。

这就是我插入的方式(使用 Magical Record):

Category *category = [Category MR_createEntity];
category.categoryName = @"My Category";

Item *itemWithCategory = [Item MR_createEntity];
itemWithCategory.itemName = @"Item with category";
itemWithCategory.category = category;

Item *itemWithoutCategory = [Item MR_createEntity];
itemWithoutCategory.itemName = @"Item without category";

[[NSManagedObjectContext MR_contextForCurrentThread] MR_saveToPersistentStoreAndWait];

sectionNameKeyPath 引用子对象上的属性并且该子对象为nil 时,为什么NSFetchedResultsController 在添加新项目时不会收到通知?

【问题讨论】:

这不仅发生在节名键路径引用相关对象时,而且当键位于获取的对象本身上时。例如,如果您将它们放在 Item.name 上,然后添加一个有名称和一个没有名称,您将看到相同的效果。但是,在这种情况下,您可以始终使用 "" 而不是 nil 来规避问题。 【参考方案1】:

尝试使用 nil 部分值对 fetchedResultsController 结果进行分区时,我遇到了非常糟糕的运气。文档没有提到,但我认为实际上是不允许的。

从文档中也不清楚,但是:您用于分段的属性实际上不一定是建模属性,并且可以是合成的。 (例如,当使用日期作为部分时,这会非常方便。)

因此,我通常的解决方法是创建一个合成只读属性,Item.formattedCategoryTitle,如果不是 nil,则返回 Item.category.categoryName,否则返回适当的占位符。也许会慢一点——我认为如果 section 属性 在数据库中,Core Data 会利用它——但它可以工作。


(P.S. 另一个小问题:文档声称“影响结果集或部分信息的上下文中的任何更改都将得到处理,并相应地更新结果。”这并不完全正确:仅对获取的实体进行更改注意到了。

在这种情况下,如果Category 对象本身发生变化(例如,分配了新标题),fetchedResultsController 将不会注意到。在这种情况下,它只注意到 Item 对象的更改 - 它们本身必须更改,控制器才能重新评估它们的存在、顺序、分区等。

如果这可能发生,您可以: 设置第二个 fetchedResultsController 只是为了观察类别的变化,并触发主控制器的重新获取;或注册NSManagedObjectContextObjectsDidChangeNotification 并在那里检测类别变化;或写Category,以便在它发生变化时“弄脏”它的项目,例如,对它们进行空更改。我已经尝试过这些方法,并且愿意听到更好的方法!)

【讨论】:

(我说“合成”而不是“瞬态”,因为 formattedCategoryTitle 根本没有存储空间;它是根据请求计算的,根本不需要建模。“瞬态”属性实际上有一个支持只是没有持久化回数据库的 ivar,可能在也可能不在模型中。)

以上是关于NSFetchedResultsController 未显示来自子对象的具有 nil 部分名称的新对象的主要内容,如果未能解决你的问题,请参考以下文章

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