NSFetchRequest fetchBatchSize 不起作用

Posted

技术标签:

【中文标题】NSFetchRequest fetchBatchSize 不起作用【英文标题】:NSFetchRequest fetchBatchSize not working 【发布时间】:2018-11-16 23:08:20 【问题描述】:

我在 NSFetchedResultsController 中遇到了 fetchBatchSize 的问题,所以我决定退后一步,只在普通的 NSFetchRequest 上使用它。我创建了一个非常简单的项目,其中只有一个包含 100 个项目的 tableViewController。这些项目只有两个属性,itemID 和 itemName。我使用以下方法填充数据数组:

func initializeItems() 
        let request = NSFetchRequest<Item>(entityName: "Item")
        let messageSort = NSSortDescriptor(key: "itemName", ascending: true)
        request.sortDescriptors = [messageSort]
        request.fetchBatchSize = 20
        do 
            let fetchedResults = try context.fetch(request)
            if fetchedResults.count > 0 
                self.items = fetchedResults
                //self.tableView.reloadData()
            
         catch 
            print("Could not fetch \(error)")
        
    

这在tableViewController的viewDidLoad中被调用。上下文定义如下:

let appDelegate = UIApplication.shared.delegate as! AppDelegate
self.context = appDelegate.persistentContainer.viewContext

当我运行该应用程序时,表格显示所有行已完全填充(如滚动条所示)。

我不明白为什么 fetchBatchSize 被忽略了。

文档如下:

获取请求中指定的对象的批量大小。 默认值为 0。批量大小为 0 被视为无限,这将禁用批量故障行为。 如果您设置一个非零批次大小,则在执行 NSFetchRequest 实例时返回的对象集合将分成批次。执行 fetch 时,会评估整个请求并记录所有匹配对象的身份,但一次只会从持久存储中获取不超过 batchSize 的对象的数据。执行请求返回的数组是一个代理对象,可以根据需要透明地对批次进行故障处理。 (在数据库术语中,这是一个内存游标。) 您可以使用此功能来限制应用程序中的工作数据集。结合 fetchLimit,您可以创建任意结果集的子范围。

我可以看到正在加载的故障数组中的 100 个项目。但随后它会在滚动 tableView 之前循环 5 次加载 20 项完整数据。 tableView 一次显示大约 15 行。

我想要的行为是在表格滚动时以 20 个项目批次加载数据

【问题讨论】:

fetchBatchSize 表示它将加载所有数据,但会逐步加载(按批次大小分页)。如果你只想加载 20 个项目,你可以使用 fetchLimit 你应该使用fetchLimit来限制记录的数量。 fetchBatchSize 应仅按 objectID 将所有条目加载到故障数组中,并按您在向下滚动并请求更多行时输入的批处理大小填充它们(在 nsfetchedresultscontroller 上自动)。这里加载了 100 行故障数组,然后在滚动之前立即以 5 个单独的 20 行批次加载所有行及其数据。出于某种原因,它立即循环了 5 20 批负载。 您找到问题的答案了吗?我面临同样的观察。 【参考方案1】:

如文档所示:

获取限制指定请求的最大对象数 执行时应该返回。

fetchLimit 是您正在寻找的。

【讨论】:

我对 fetchLimit 非常熟悉,但这不是我想要的。我正在寻找使用 fechBatchSize【参考方案2】:

我怀疑您的代码中的某些内容实际上会遍历该数组并导致它触发错误。我不是在告诉你自己故意这样做——你的 UITableView 的设置很可能会这样做(根据内容、切片数据等预先计算单元格高度)。

我的建议是在 Instruments 中打开 Core Data 分析工具,并在触发故障时检查堆栈跟踪中的内容。

【讨论】:

【参考方案3】:

fetchBatchSize 最适合 NSFetchedResultsController。将您的 fetchRequest 放入 NSFetchedResultsController 中,然后使用 NSFetchedResultsController 访问获取的结果。然后肯定 fetchBatchSize 会起作用。或者你可以谷歌 NSFetchedResultsController 在获取结果时是如何实现的。

【讨论】:

以上是关于NSFetchRequest fetchBatchSize 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

如何将类型应用于NSFetchRequest实例?

核心数据 - NSFetchRequest 问题

如何将类型应用于 NSFetchRequest 实例?

如何将类型应用于 NSFetchRequest 实例?

具有不同属性的 NSFetchRequest

这个 NSFetchRequest 有啥问题?