Is it possible to use background thread on NSFetchedResultsController for heavy read operation to ensure UI responsiveness?

Apple has shown us how to perform heavy write operation using background thread (by using newBackgroundContext) in their official earth quake example - https://github.com/yccheok/earthquakes-WWDC20

But, what about heavy read operation? (millions of rows for stress test purpose)

We would also like our app UI to be responsiveness, when we are launching the app for first time, and the app is reading a large amount of data from CoreData.

The following is the code snippet which is using NSFetchedResultController.





[UI is not responsiveness if there are a lot of rows]
Code Block
let controller = NSFetchedResultsController(fetchRequest: fetchRequest,
managedObjectContext: persistentContainer.viewContext,
sectionNameKeyPath: nil, cacheName: nil)
controller.delegate = fetchedResultsControllerDelegate
// Perform the fetch.
do {
// This statement tooks some time to complete if you have a lot of rows.
try controller.performFetch()
} catch {
fatalError("Unresolved error \(error)")
}




[UI is not responsiveness if there are a lot of rows]


We try to perform controller.performFetch() using background thread. Still, but not sure why, the UI is still not responsiveness. My guess is that, after NSFetchedResultsController is occupied UI main thread, to perform some time consuming I/O read operation.
Code Block
let controller = NSFetchedResultsController(fetchRequest: fetchRequest,
managedObjectContext: persistentContainer.viewContext,
sectionNameKeyPath: nil, cacheName: nil)
controller.delegate = fetchedResultsControllerDelegate
DispatchQueue.global(qos: .background).async {
// Perform the fetch.
do {
// This statement tooks some time to complete if you have a lot of rows.
try controller.performFetch()
} catch {
fatalError("Unresolved error \(error)")
}
}




[UI is responsive now. But the solution is incorrect...]

I guess, we need to place NSFetchedresultController under background thread too. Hence, we do the following modification.
Code Block
let backgroundContext = persistentContainer.newBackgroundContext()
let controller = NSFetchedResultsController(fetchRequest: fetchRequest,
managedObjectContext: backgroundContext,
sectionNameKeyPath: nil, cacheName: nil)
controller.delegate = fetchedResultsControllerDelegate
backgroundContext.perform {
// Perform the fetch.
do {
// This statement tooks some time to complete if you have a lot of rows.
try controller.performFetch()
} catch {
fatalError("Unresolved error \(error)")
}
}

The UI is responsiveness during fetching, and data is able to be fetched and shown after some time.

However, if we investigate further by using the launching argument

Code Block
-com.apple.CoreData.ConcurrencyDebug 1


We will experience the following crash after controller.performFetch() finish executed.

Code Block
CoreData`+[NSManagedObjectContext __Multithreading_Violation_AllThatIsLeftToUsIsHonor__]:


May I know, is it ever possible to make UI responsive, when we are using NSFetchedResultController to load a large amount of data (few millions rows as per testing)?

Can NSFetchedResultController ever operated under background thread?

Is it possible to use background thread on NSFetchedResultsController for heavy read operation to ensure UI responsiveness?
 
 
Q