来自父

时间:2016-03-12 18:54:02

标签: ios swift core-data nsfetchedresultscontroller

我希望在更新父上下文时更新子上下文。

我有一个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?
}
}

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

  

我试图将此控制器与它自己的私有语境一起使用   它的更新并没有阻止UI

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