【发布时间】:2015-12-13 03:09:15
【问题描述】:
最近我正在开发一个允许一次创建和浏览大量数据的应用程序。
在此应用程序中,可以在单个时间点从NSFetchedResultsController 在collectionView 中查看 2,000 多个对象。
在测试这个场景时,很快就发现并验证了NSFetchedResultsController 在访问批处理索引时没有最佳地将NSManagedObjects 分页进出内存。
由于从NSFetchedResultsController 访问索引并且加载了更多NSManagedObjects,NSFetchedResultsController 似乎会将先前加载的NSManagedObjects 保留在内存中,而不是根据访问的索引集将它们分页进出内存使用fetchRequest 中设置的fetchBatchSize。为了进一步解释这一点,如果 fetchBatchSize 设置为 45,并且现在加载了索引 1,000,则 NSFetchedResultsController 似乎保留了在索引 1,000 之前通过索引访问加载的所有内容的内存,而这些内容是通过索引访问而不是错误的。
如果在父上下文中调用managedObjectContext.reset(),内存会被正确释放,直到通过索引访问再次加载对象。 fetchBatchSize 似乎只能阻止一次加载所有数据。访问索引时,NSFetchedResultsController 似乎会加载新批次,同时保留先前加载的批次。
我目前的想法正在引导我创建自己的分页,其中我将有多个 fetchResultsControllers 与 fetchBatchSizes 和 fetchLimits... 这似乎比它应该复杂得多。这将创建一种手动方式将数据从内存中分页出来,从而允许正确的内存管理。
我的问题是是否有更好的方法来解决这个问题?我本质上想在使用 CoreData 时对类似于 Apple 的照片应用程序的无限对象进行分页(它们的性能让我大吃一惊)。
注意:关于这个确切问题的帖子有很多,指出人们必须制定手动解决方案来改进内存管理(例如:link#1、link#2)。我不是在寻找“你忘了这个”或“你可能做错了”的答案。我可以毫无疑问地验证,我正确地使用了记录在案的 API。我正在寻找一种有助于更好地管理NSFetchedResultsController 内存的解决方案。设置fetchBatchSize 是一个临时解决方案,直到用户加载大量索引导致内存警告被触发并且我重置managedObjectContext。之前提到过,是的,我已经测试过设置和不设置 NSFetchedResultsController 缓存并相应地重置.... -如此。
【问题讨论】:
-
fetchBatch?你的意思是fetchBatchSize? -
是的,我没有复制/粘贴确切的函数名称,只是简单介绍了总体思路/概念
-
您是否考虑过使用
refreshObject:object mergeChanges:NO手动故障排除不需要的对象? -
是的,我开始走这条路,并意识到它比什么都烦人。在尝试适当地对对象进行故障处理和取消故障处理时,我开始遇到重大问题。 (正如提醒我的堆栈是 privateContext -> mainContext -> privateContext Spawns)。我会使用核心数据变量的副本创建一个内存对象,然后将该变量传回,如果发生变化并且获取结果控制器在调用的地方委托,这就是我遇到主要问题的地方。
-
已知嵌套上下文存在错误,例如不遵守
fetchBatchSize设置。您是否在直接连接到 PSC 的单一主要上下文中尝试过此操作?我认为每个上下文有可能有 1000 个对象物化,如果它们与其他物化对象有关系,它们可能不会出错。
标签: ios performance core-data nsfetchedresultscontroller nsfetchrequest