I have been having problems with fetchBatchSize in an NSFetchedResultsController so I decided to take a step back and use it on just a plain NSFetchRequest. I created a very simple project with only a tableViewController that has 100 items. The items have only two properties, itemID and itemName. I use the following method to populate the data array:
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)")
}
}
This is called in viewDidLoad of the tableViewController. The context is defined as follows:
let appDelegate = UIApplication.shared.delegate as! AppDelegate
self.context = appDelegate.persistentContainer.viewContext
When I run the app, the table shows fully populated (as indicated by the scroll bar) with all rows.
I don't understand why the fetchBatchSize is being ignored.
Documentation is as follows:
The batch size of the objects specified in the fetch request. The default value is 0. A batch size of 0 is treated as infinite, which disables the batch faulting behavior. If you set a nonzero batch size, the collection of objects returned when an instance of NSFetchRequest is executed is broken into batches. When the fetch is executed, the entire request is evaluated and the identities of all matching objects recorded, but only data for objects up to the batchSize will be fetched from the persistent store at a time. The array returned from executing the request is a proxy object that transparently faults batches on demand. (In database terms, this is an in-memory cursor.) You can use this feature to restrict the working set of data in your application. In combination with fetchLimit, you can create a subrange of an arbitrary result set.
I can see the 100 items in the fault array being loaded. But then it loops through 5 loads of 20 items full data prior to scrolling the tableView. The tableView shows about 15 rows at a time.
The behaviour I want is for the data to be loaded in 20 item batches as the table is scrolled