我想了解为什么fetchBatchSize无法与NSFetchRequest一起正常工作。

初始读取时,在加载故障阵列后,将通过batchSize循环加载数据阵列,直到加载了所有数据,而不是直到仅加载了所需的数据为止。使用coreData工具或编辑运行方案可以清楚地显示批处理数量项循环中加载的所有项数据,直到加载了所有数据,而不是仅加载出现在tableView中的那些行的数据。

预期结果:

期望故障阵列中的所有项目都将被加载,然后仅第一批作为要加载的数据。

实际结果:

在滚动之前,将所有项目加载到故障阵列中,然后将所有数据加载到具有批处理大小的循环批处理中。

这是我创建的示例项目viewController来证明这一点:

import UIKit
import CoreData

class BatchTestTableViewController: UITableViewController {

    var context: NSManagedObjectContext!
    var items: [Item]?

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.register(UINib(nibName: "BatchTableViewCell", bundle: nil), forCellReuseIdentifier: "BatchTableViewCell")

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

        self.initializeItems()

        if items != nil {
            if items!.count == 0 {
                for i in 0..<10000 {
                    let entityDescription =  NSEntityDescription.entity(forEntityName: "Item", in: context)
                    let item = Item(entity: entityDescription!, insertInto: self.context)
                    item.objectId = UUID().uuidString
                    item.itemId = UUID().uuidString
                    item.itemName = "\(i)"

                }
                try? context.save()
                self.initializeItems()
            }
        }
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if items != nil {
            return items!.count
        }
        return 0
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "BatchTableViewCell", for: indexPath) as! BatchTableViewCell
        let item = self.items![indexPath.row]
        cell.itemNameLabel.text = item.itemName
        return cell
    }

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 50
    }

    // MARK: - Helper Methods

    func initializeItems() {
        let request = NSFetchRequest<Item>(entityName: "Item")
        let messageSort = NSSortDescriptor(key: "itemName", ascending: true)
        request.fetchBatchSize = 20
        request.sortDescriptors = [messageSort]

        do {
            self.items = try context.fetch(request)
        } catch {
            print("Could not fetch \(error)")
        }
    }

}


以下是从CoreData Instruments读取的内容:

ios - fetchBatchSize在NSFetchRequest上不起作用-LMLPHP

从coredata仪器的上图可以看出,所有数据都以20个批处理大小的循环加载,直到在滚动tableView之前加载了所有10,000个项目。

最佳答案

fetchBatchSize不会限制您的数据获取。在您的情况下,它使fetchRequest可以按20个批处理来提取数据。您可以使用此功能来限制应用程序中的数据工作集。与fetchLimit结合使用,可以创建任意结果集的子范围。您应该一起使用fetchLimit

    request.fetchLimit = 20


From Apple doc


  执行提取时,将评估整个请求并记录所有匹配对象的身份,但是一次只能从持久性存储中提取不超过batchSize的对象数据。从执行请求返回的数组是一个代理对象,可以按需透明地对批处理进行故障处理。 (用数据库术语来说,这是一个内存游标。)

关于ios - fetchBatchSize在NSFetchRequest上不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51228685/

10-10 21:01