【问题标题】:Child NSManagedObjectContext update from parent从父更新子 NSManagedObjectContext
【发布时间】:2016-03-12 18:54:02
【问题描述】:

我想在父上下文更新后更新子上下文。

我有一个使用子上下文的 NSFetchedResultsController,然后我想通过它的委托更新 UI - 我不确定这是否完全正确,这就是我现在正在做的事情:

我创建了一个从支持我的模型的类中的 Web 服务更新的子上下文。这是一个简化的例子:

class Messages {

var pmoc: NSManagedObjectContext!
var delegate: MessagesDelegate?

init() {

    let appDel  = UIApplication.sharedApplication().delegate as! AppDelegate
    let moc     = appDel.managedObjectContext

    let pmoc = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
    pmoc.parentContext = moc
    self.pmoc = pmoc
}

func dataToUpdatePrivateContextReceived() {

    // Add things to the private moc
    self.pmoc.performBlock { () -> Void in

        // Create new NSManagedOBject, etc.
        self.savePMOC()
    }
}

func savePMOC() {

    self.pmoc.performBlock { () -> Void in

        do {

            try self.pmoc.save()
            // save main context through an abstraction...
            // Inform any delegate a save has taken place
            self.delegate?.pmocSavedIntoMain()

        } catch let error as NSError {

            print("Save pmoc error :\(error.localizedDescription)")
        }
    }
}
}

protocol MessagesDelegate {
    func pmocSavedIntoMain()
}

然后在一些 UIViewController 中,我使用 NSFetchedResultsController 更新 UITableView,我尝试将此控制器与它自己的私有上下文一起使用,因此它的更新不会阻塞 UI。 另一个简化的例子:

class ViewController: UIViewController {

var fetchedResultsController: NSFetchedResultsController!
var viewPMOC: NSManagedObjectContext!
let messages = Messages()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    messages.delegate = self

    let appDel  = UIApplication.sharedApplication().delegate as! AppDelegate
    let moc     = appDel.managedObjectContext

    let pmoc = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
    pmoc.parentContext = moc
    self.viewPMOC = pmoc

    let fr = NSFetchRequest(entityName: "MyEntity")
    fr.fetchBatchSize = 20

    let sort = NSSortDescriptor(key: "id", ascending: false)
    fr.sortDescriptors = [sort]

    self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fr,
        managedObjectContext: self.viewPMOC,
        sectionNameKeyPath: nil,
        cacheName: nil)

    self.fetchedResultsController.delegate = self

    do {

        try self.fetchedResultsController.performFetch()

    } catch let error as NSError {

        print("vdl fetch error is: \(error.localizedDescription)")
    }
}
}

extension ViewController: NSFetchedResultsControllerDelegate {

func controllerWillChangeContent(controller: NSFetchedResultsController) {
    // dispatch begin updates on maind thread
}

func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
    // handle update type on main thread
}

func controllerDidChangeContent(controller: NSFetchedResultsController) {
    // dispatch end upds on main thread
}
}

extension ViewController: MessagesDelegate {
func pmocSavedIntoMain() {
    // what can I do here to get the child context to update from
    //parent and thus trigger the fetched results controller to update the view?
}
}

【问题讨论】:

    标签: ios swift core-data nsfetchedresultscontroller


    【解决方案1】:

    获取结果控制器需要一个主上下文。

    使用此模式摆脱“断断续续”。

    RootContext (private queue) - saves to persistent store
    MainContext (main queue) child of RootContext - use for UI (FRC)
    WorkerContext (private queue) - child of MainContext - use for updates & inserts
    

    您的网络查询已完成,创建工作人员上下文并更新数据模型。当您save 时,更改将被推送到主上下文,并且您的 UI 应该通过 FRC 委托更新。保存主上下文和根上下文以保持不变。

    确保在处理子上下文时始终使用块方法 performBlockperformBlockAndWait

    【讨论】:

    • 啊哈!我从没想过要这样做,但看到这样的情况非常有意义。我会尽快更新我的项目,谢谢!
    • 从数据库中获取对象怎么样?哪种上下文最适合使用?
    • @PabloMartinez FRC 应该在性能方面考虑到这一点,因此您不需要后台线程来获取。
    【解决方案2】:

    我正在尝试将此控制器与它自己的私有上下文一起使用,所以 它的更新不会阻塞用户界面

    FRC 在生活中的工作是更新 UI - 这个应该在主线程上,而不是像你提到的那样,加载数据的私有上下文。我会将 FRC 放回您的主要上下文中(当您将子上下文保存为 up 时,它将自动更新),除非您遇到性能问题,否则将其保留在那里。然后你可以看看更奇特的东西,但 FRC 旨在通过诸如 batchSize 之类的东西来保持高性能。

    【讨论】:

    • 当我有很多更新并调用 insertRow 时,它会变得非常不稳定,这似乎开始减轻其中的一部分。当更新存在后保存回主上下文时,我只是错过了。
    • 看看这个问题的实现:stackoverflow.com/questions/31722142/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-26
    • 1970-01-01
    • 2015-07-13
    • 2016-12-24
    • 1970-01-01
    • 2016-08-24
    • 2019-12-05
    相关资源
    最近更新 更多