【问题标题】:NSManagedObjectContextObjectsDidChanged not being calledNSManagedObjectContextObjectsDidChanged 未被调用
【发布时间】:2016-05-21 14:26:54
【问题描述】:

插入或更改对象时,我没有收到 NSManagedObjectContextObjectsDidChanged 通知。上下文有一个父上下文,这可能是个问题吗?在父上下文中获取通知没有问题。

这就是我创建子上下文的方式:

func createPrivateContext() -> NSManagedObjectContext{
    let privateManagedObject = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
    privateManagedObject.parentContext = self.managedObjectContext
    privateManagedObject.mergePolicy = NSOverwriteMergePolicy
    return privateManagedObject
}

这就是我将观察者添加到通知中心的方式:

self.privateMOC = appDelegate.createPrivateContext()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "objectsDidChanged:", name: NSManagedObjectContextObjectsDidChangeNotification, object: self.privateMOC!)

如何在子上下文中插入新对象:

let privateMoc = getPrivateMoc()
let newTask = Task.createNewTaskInManagedObjectContext(privateMoc)
try! privateMoc.obtainPermanentIDsForObjects([newTask])

预计会通知对象已插入,但我从未收到通知。

更新: 将子 MOC 从 PrivateConcurrencyType 更改为 MainQueueConcurrencyType 时,通知确实有效。

【问题讨论】:

    标签: ios cocoa-touch core-data


    【解决方案1】:

    问题在于修改对象所在的线程。如果子上下文是使用 PrivateConcurrencyType 创建的,则需要更改子上下文的执行块内的对象。

    privateMOC?.performBlock({ () -> Void in
        let newTask = Task.createNewTaskInManagedObjectContext(privateMoc)
        print(newTask.objectID.URIRepresentation().absoluteString)
        try! privateMoc.obtainPermanentIDsForObjects([newTask])
        print(newTask.objectID.URIRepresentation().absoluteString)
    })
    

    【讨论】:

    • PerformBlock 方法应该用于任何基于队列的上下文。
    • 正确,设置属性时除外
    • 这是不正确的。托管对象及其属性归上下文所有。访问属性不是线程安全的,应该通过 perform 块方法来完成。
    • 查看文档。
    • 我很清楚NSManagedObjectContext 文档指出:“基于队列的托管对象上下文上的设置器方法是线程安全的。”这是指托管对象上下文上的属性方法,而不是它拥有的托管对象。托管对象属性不是线程安全的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-07
    • 2012-02-15
    • 2011-11-17
    • 2019-10-22
    • 2016-04-03
    • 2010-09-20
    • 2020-05-23
    相关资源
    最近更新 更多