Search code examples
ioscore-datansfetchedresultscontroller

NSFetchedResultsController with privateQueueConcurrencyType - changes do not call delegate methods


I'm unable to get my NSFetchedResultsControllerDelegate methods called when setting the NSFetchedResultsControllerDelegate up with a concurrencyType value of privateQueueConcurrencyType.

Consider this example:

fileprivate lazy var fetchedResultsController: NSFetchedResultsController<Note> = {
    // Initialize Fetch Request
    let fetchRequest: NSFetchRequest<Note> = Note.fetchRequest()

    // Add Sort Descriptors
    let sortDescriptor = NSSortDescriptor(key: "updatedAt", ascending: false)
    fetchRequest.sortDescriptors = [sortDescriptor]

    // Initialize Fetched Results Controller
    let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.coreDataManager.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)

    // Configure Fetched Results Controller
    fetchedResultsController.delegate = self

    return fetchedResultsController
}()

Where the coreDataManager class has this:

private(set) lazy var managedObjectContext: NSManagedObjectContext = {
    let managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)

    managedObjectContext.persistentStoreCoordinator = self.persistentStoreCoordinator

    return managedObjectContext
}()

If I call fetchedResultsController.managedObjectContext.delete(note) and then save, the controller:didChangeObject:atIndexPath:forChangeType:newIndexPath method is called and I can respond to the deletion of the note object.

If I change the code above to be:

fileprivate lazy var fetchedResultsController: NSFetchedResultsController<Note> = {
    // Initialize Fetch Request
    let fetchRequest: NSFetchRequest<Note> = Note.fetchRequest()

    // Add Sort Descriptors
    let sortDescriptor = NSSortDescriptor(key: "updatedAt", ascending: false)
    fetchRequest.sortDescriptors = [sortDescriptor]

    let managedObjectContext = NSManagedObjectContext(concurrencyType: .concurrencyType`)

    managedObjectContext.persistentStoreCoordinator = self.coreDataManager.managedObjectContext.persistentStoreCoordinator

    // Initialize Fetched Results Controller
    let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)

    // Configure Fetched Results Controller
    fetchedResultsController.delegate = self

    return fetchedResultsController
}()

Which specifically changes the managed object context 'usage' from using self.coreDataManager.managedObjectContext to a new version that should work on a background thread, the delegate methods are never called when items are deleted.

So my main question is - how do I get the NSFetchedResultsControllerDelegate methods to be called when using this type of NSManagedObjectContext?


Solution

  • The fetchedResultsController is monitoring the context that you just created and that context is not processing updates. If you want this context to change you have to set automaticallyMergesChangesFromParent = true for the context.