我在使用Core Data和NSArrayController的OS X应用程序中遇到了一些奇怪的行为。发送到阵列控制器的每个fetch:消息都会导致持久性存储(sqlite)中的 double fetch ,当然需要两倍的时间来进行提取。
当我设置数组控制器的fetchPredicate属性然后发送fetch:message时会发生这种情况。
我使用标准苹果核心数据应用模板创建了一个简单的测试应用,其中一个实体'SomeEntity'只有一个属性'stringAttribute'。我将NSArrayController子类化并覆盖了fetchWithRequest:merge:error:设置断点并查看数组控制器何时从存储中获取。
然后,我写了一个简单的动作方法(连接到按钮),只包含两行:
self.arrayController.fetchPredicate = [NSPredicate predicateWithFormat:@"TRUEPREDICATE"];
[self.arrayController fetch:self];
而且,每次按下按钮时,fetchWithRequest:merge:error:方法被调用两次,导致两次访问持久性存储。
NSArrayController继承自实现fetch:方法的NSObjectController。文档说
从OS X v10.4开始,此方法的结果将推迟到runloop的下一次迭代,以便错误呈现机制可以作为工作表提供反馈。
fetchWithRequest:merge:error:确实由运行循环机制中触发的NSInvocation调用。在一个小断点设置后,我发现一行NSInvocation由行
创建self.arrayController.fetchPredicate = [NSPredicate predicateWithFormat:@"TRUEPREDICATE"];
和下一行的第二个
[self.arrayController fetch:self];
当我注释掉第二行时,控制器根本没有取出。因此,只要我想在获取之前设置fetch谓词,我就会得到两次提取。奇怪的是,当我在应用程序启动后第一次按下我的按钮时,就不会发生这种情况。
这感觉很奇怪,因为我基本上只在标准的Core Data堆栈中添加了两行代码。当我用测试数据填充商店并测量时间fetchWithRequest:merge:error:需要完成,我可以清楚地看到两次获取的性能问题并花费两倍的时间。
直接调用fetchWithRequest:merge:error:不是理想的解决方案,因为NSArrayController中有一些自动化功能,我必须重新实现自己。并且它不应该是首先设置fetchPredicate而不是简单地调用fetch的正确方法:?
这里有什么想法?