具有 privateQueueConcurrencyType 的 NSFetchedResultsController - 更改不调用委托方法

NSFetchedResultsController with privateQueueConcurrencyType - changes do not call delegate methods

在将 NSFetchedResultsControllerDelegate 设置为 privateQueueConcurrencyTypeconcurrencyType 值时,我无法调用我的 NSFetchedResultsControllerDelegate 方法。

考虑这个例子:

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
}()

coreDataManager class 有这个:

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

    managedObjectContext.persistentStoreCoordinator = self.persistentStoreCoordinator

    return managedObjectContext
}()

如果我调用fetchedResultsController.managedObjectContext.delete(note)然后保存,调用controller:didChangeObject:atIndexPath:forChangeType:newIndexPath方法,我可以响应删除笔记对象。

如果我把上面的代码改成:

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
}()

它专门将托管对象上下文 'usage' 从使用 self.coreDataManager.managedObjectContext 更改为应该在后台线程上工作的新版本,删除项目时永远不会调用委托方法。

所以我的主要问题是 - 如何在使用这种类型的 NSManagedObjectContext 时调用 NSFetchedResultsControllerDelegate 方法?

fetchedResultsController 正在监视您刚刚创建的上下文,该上下文未处理更新。如果您希望更改此上下文,则必须为上下文设置 automaticallyMergesChangesFromParent = true

正如 John 所说,NSFetchedResultsController 仅监控关联的托管上下文,例如

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
    }()

.privateQueueConcurrencyType 继承你的 .mainQueueConcurrencyType 就像下面的代码

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
    }()

不要忘记在主上下文中添加 context.automaticallyMergesChangesFromParent = true 以通知 privateQue 上下文的后台操作。

我希望这会奏效