fetchBatchSize在NSFetchRequest上不起作用

时间:2018-07-08 03:48:05

标签: ios swift xcode core-data nsfetchrequest

我想了解为什么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读取的信息:

enter image description here

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

1 个答案:

答案 0 :(得分:0)

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

    request.fetchLimit = 20

From Apple doc

  

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