NSFetchedResultsController 在托管对象被修改时通知其委托删除更改,并且从不通知插入或更新
Posted
技术标签:
【中文标题】NSFetchedResultsController 在托管对象被修改时通知其委托删除更改,并且从不通知插入或更新【英文标题】:NSFetchedResultsController notifies its Delegate of delete changes when a managed object is modified, and never notifies for Insert or Update 【发布时间】:2016-06-01 21:43:12 【问题描述】:我有一个UITableViewController
,它是NSFetchedResultsController
的代表。我的NSFetchedResultsControllerDelegate
函数是根据Apple's documentation 中的“典型用途”设置的,表格视图控制器作为获取的结果控制器的委托属性。
我还有一些视图控制器,它们显示在可以修改托管对象的表视图顶部。这些修改是在 same 托管对象上下文中完成的。我的应用程序中只构建了一个托管对象上下文,并且可以全局访问它。 (我在对象上下文构造中放置了一些 print
语句,以确保我不会意外地在其他地方重新构造它。)
当我修改其中一个托管对象时,会调用委托函数controller:didChangeObject
,但NSFetchedResultsChangeType
总是 .Delete
。当我创建一个托管对象时,委托函数根本不会触发。
但是,当我手动调用 call performFetch()
和 tableView.reloadData()
时,单元格会恢复到正确的状态:删除的行又回来了,所有未插入的行都会创建。
结果是删除对象按预期工作(删除单元格),但对对象的更新会导致其单元格被删除,并且对象创建不会触发单元格插入。
我尝试为这种行为创建一个简单的演示,但是当我从一个空白应用程序重新创建这种情况时,我看不到这种行为。所以我的应用程序中的某些东西导致了这种奇怪的行为,但我不知道是什么。有什么想法吗?
额外信息:
谓词和排序描述符的实际构造是在几个不同的类上完成的,但是通过print(resultsController.fetchRequest.predicate)
和print(resultsController.fetchRequest.sortDescriptors)
打印它们会得到以下结果:
可选(readState == "2" OR readState == "1")
可选([(readState,升序,比较:),(标题,升序,比较:)])
我在我的controller:didChangeObject:
方法中添加了一个打印语句,我可以看到它只被type.rawValue = 2
(即.Delete
)调用,并且仅在我修改对象时调用,而不是在我创建对象时调用。
【问题讨论】:
如果在更新时删除了单元格,如果与实际上下文内容不匹配,我希望您会崩溃...我想您应该删除 SQL 文件并重试。然后删除并重新创建模型。我认为对此没有合理的解释...... 您是否为 FRC 指定谓词?如果是这样,更新是否会导致对象被谓词排除,从而从 TV 中删除? @pbasdf 好主意,但在这种情况下不是解决方案。我确实指定了一个谓词,但这不会阻止对象被包含在内。当我重新获取并在表上调用 reloadData 时(仍然使用谓词),单元格返回 请向我们展示您的 FRC 初始化代码,特别是predicate
构造部分。
好吧,也许这会有所帮助:***.com/a/12514826/826716。这是关于具有关系使用的复杂排序描述符。根据我的经验,它也发生在谓词上。因此,如果您可以向我们展示您的实际谓词和排序描述符 - 它可能有助于确定这种不当行为的根源。在 FRC 分配行和po fetchRequest.predicate
和po fetchRequest.sortDescriptors
处设置断点。
【参考方案1】:
这与NSFetchedResultsController
处理其NSPredicate
的方式不一致。
如果NSFetchedResultsController
是由一个获取请求构造的,该请求具有一个谓词,该谓词在整数和字符串之间进行比较,如下所示:
let predicate = NSPredicate(format: "integerAttribute == %@", String(1))
这将导致谓词字符串为:
integerAttribute == "1"
在这种情况下,初始提取工作正常:在提取结果控制器上调用函数 performFetch()
返回所有对象,其中 integerAttribute
等于 1
(其中 integerAttribute
的类型为 Int32
)。
但是,NSFetchedResultsControllerDelegate
的通知无法正常工作。托管对象的修改会导致代理收到NSFetchedResultsChangeType.Delete
更改的通知。托管对象的创建根本不调用委托。
要消除所有这些怪异现象,请按如下方式修复谓词格式字符串:
let predicate = NSPredicate(format: "integerAttribute == %d", 1)
【讨论】:
以上是关于NSFetchedResultsController 在托管对象被修改时通知其委托删除更改,并且从不通知插入或更新的主要内容,如果未能解决你的问题,请参考以下文章