从后台线程使用 Core Data 托管上下文......你如何正确地做到这一点?

Posted

技术标签:

【中文标题】从后台线程使用 Core Data 托管上下文......你如何正确地做到这一点?【英文标题】:Using CoreData managedContext from background thread...how do you do it correctly? 【发布时间】:2020-09-17 01:34:49 【问题描述】:

我打开了 CoreData 并发调试器,并且我在每个地方都在断言。我想不通。

我在后台线程上创建了我认为的上下文。请看一下我的 CoreData Stack:

import Foundation
import CoreData

class CoreDataManager 

  lazy var managedContext: NSManagedObjectContext = 
    return self.storeContainer.viewContext
  ()
  
  lazy var backgroundContext: NSManagedObjectContext = 
    
    return self.storeContainer.newBackgroundContext()
  ()
  
  lazy var privateMOC: NSManagedObjectContext = 
    let pMOC = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
    pMOC.parent = self.storeContainer.viewContext
    return pMOC
  ()
  
  private lazy var storeContainer: NSPersistentContainer = 
    let container = NSPersistentContainer(name: "XXXX")
    
    
    container.loadPersistentStores(completionHandler:  (storeDescription, error) in
      if let error = error as NSError? 
        print("Unresolved error \(error), \(error.userInfo)")
      
    )
    return container
  ()
    
  func saveContext () 
    guard managedContext.hasChanges else  return 
    
    do 
      try managedContext.save()
     catch let error as NSError 
        print("Unresolved error \(error), \(error.userInfo)")
    
    
    self.reset()
  
  
  func reset() 
    managedContext.reset()
  
  

然后我尝试从存储库类型类中的后台线程执行任务:

  func deleteAllData() 
    let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Pairing")
    let pairings = (try? self.coreDataManager.privateMOC.fetch(fetchRequest)) as! [Pairing_ManagedObject]. // I GET THE ASSERT HERE
    for pairing in pairings 
      self.coreDataManager.privateMOC.delete(pairing)
    
    self.coreDataManager.saveContext()
  

我该如何做到这一点,这样我就不会得到核心数据并发断言并正确地做到这一点?请帮忙。

【问题讨论】:

所以我想我发现了如何使用 .perform 块写入 privateMOC 上下文。但是现在我保存到私有上下文的对象不在 mainContext 中。我如何同步它们。这太复杂了。我一定是做错了什么 你可以试试this 吗? 【参考方案1】:

您正在使用私有队列并发创建一个新的托管对象上下文,但这还不足以避免并发问题。 Core Data 的政策是您必须使用performBlockperformBlockAndWait 来执行使用该上下文的所有操作。在您的代码中,这意味着 deletesave 调用必须使用其中一个函数来完成。

还有第二个问题。您正在使用 saveContext 函数来保存更改。但这不会保存您的私有队列上下文的更改。它节省了一些称为managedContext 的其他上下文。保存一个上下文不会自动保存其他上下文。如果您想对私有队列上下文进行更改并保存这些更改,则需要在某个时候保存该上下文。

【讨论】:

以上是关于从后台线程使用 Core Data 托管上下文......你如何正确地做到这一点?的主要内容,如果未能解决你的问题,请参考以下文章

Core Data 3 托管对象上下文

Core Data 托管对象上下文线程同步

Core Data 使用多个上下文中的新对象从后台线程订购一对多关系保存

Core Data,在后台线程中修改 NSManagedObject

如何在Core Data中同步两个独立的NSManagedObjectContext?

使用Core Data将文本从文本字段分配到托管对象上下文