简体   繁体   中英

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 ?

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.

As John told NSFetchedResultsController is monitoring only associated managed context like

 lazy var fetchedResultsController: NSFetchedResultsController = { () -> NSFetchedResultsController<NSFetchRequestResult> in let request = NSFetchRequest<NSFetchRequestResult>.init(entityName: "Repository") let descriptors = [NSSortDescriptor.init(key: "name", ascending: true), NSSortDescriptor.init(key: "name", ascending: true)] request.sortDescriptors = descriptors let resultsController = NSFetchedResultsController.init(fetchRequest: request, managedObjectContext: CoreDataManager.shared.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil) resultsController.delegate = self return resultsController }() 

Inherit your .mainQueueConcurrencyType from .privateQueueConcurrencyType like below code

 lazy var managedObjectContext: NSManagedObjectContext = { let context = NSManagedObjectContext.init(concurrencyType: .mainQueueConcurrencyType) context.parent = self.privateQueueManagedObjectContext context.automaticallyMergesChangesFromParent = true return context }() lazy var privateQueueManagedObjectContext: NSManagedObjectContext = { let context = NSManagedObjectContext.init(concurrencyType: .privateQueueConcurrencyType) context.persistentStoreCoordinator = self.persistentStoreCoordinator return context }() 

Dont forget to add context.automaticallyMergesChangesFromParent = true in your maincontext to notify background operations on privateQue context.

I hope this will work

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM