我希望有人可以解释为什么在释放源/主机对象时,以下示例中的关联对象不会自动解除分配。下面的示例代码有点人为(道歉提前),但它解释了我的问题。NSManagedObjectContext释放问题 - (Swift |相关对象)
的例子假设一个CoreData实体Product
与字符串属性sku
和由Xcode的模板提供的默认CoreData堆栈:
import UIKit
import CoreData
class ViewController: UIViewController {
@IBAction func createProduct(sender: AnyObject) {
let context = CoreDataHelpers.vendBackgroundWorkerContext()
let newProduct = CoreDataHelpers.newProduct(context: context)
newProduct.sku = "8-084220001"
do {
try newProduct.managedObjectContext?.save()
print("Product created [SKU: \(newProduct.sku ?? "NotDefined")]")
} catch {
print(error)
}
}
}
public class CoreDataHelpers {
public static let mainContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
public class func vendBackgroundWorkerContext() -> NSManagedObjectContext {
let managedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
managedObjectContext.parentContext = self.mainContext
return managedObjectContext
}
class func newProduct(context context: NSManagedObjectContext) -> Product {
let newProduct = NSEntityDescription.insertNewObjectForEntityForName("Product", inManagedObjectContext: context) as! Product
return newProduct
}
}
执行createProduct
功能时,一个新的PrivateQueueConcurrencyType管理对象上下文(MOC)将由新的Product
管理对象(MO)出售和使用。上述代码到目前为止工作正常。
但是!如果我结合createProduct
功能的前两行这样的:
let newProduct = CoreDataHelpers.newProduct(context: CoreDataHelpers.vendBackgroundWorkerContext())
然后应用程序将在try newProduct.managedObjectContext?.save()
崩溃了EXC_BAD_ACCESS
。乍一看,这看起来有点奇怪 - 因为我们所做的一切都是重构代码。挖掘到documentation,managedObjectContext
属性被宣布为unowned(unsafe)
。这可能意味着已创建的MOC已被释放,并且我们有一个悬挂指针(如果我的假设错误,请纠正我)。
为了确保MOC不会被释放,我尝试将它与MO本身相关联。 newProduct
:
class func newProduct(context context: NSManagedObjectContext) -> Product {
let newProduct = NSEntityDescription.insertNewObjectForEntityForName("Product", inManagedObjectContext: context) as! Product
var key: UInt8 = 0
objc_setAssociatedObject(newProduct, &key, context, .OBJC_ASSOCIATION_RETAIN)
return newProduct
}
这似乎工作很好 - 直到我签入仪器。这样看来,当Product
MO被释放,现在相关的MOC不(不应该当源对象被释放时会自动释放?)
我的问题是: 有人能解释其中附加参考是否阻止它被释放的MOC?我是否在MO和MOC之间创建了一个保留周期?
为什么不应该按需要销毁/创建工作环境?例如。两个正在改变的MO尚未持续。如果在相同的环境下,一次保存将会持续两次 - 你可能只是想坚持其中的一次)。值得注意的CD堆栈出售多个工作者上下文(例如https://www.bignerdranch.com/blog/introducing-the-big-nerd-ranch-core-data-stack/)。 –
@SOOverIt你说得对,我已经删除了我答案的最后部分。但是,您仍然需要确保您对所使用的任何托管上下文有强烈的参考。 – Sulthan
您提到'每个托管对象都属于托管上下文'。这不完全正确。您仍然可以拥有已删除上下文的托管对象。请参阅NSManagedObject类参考中的managedObjectContext参考文档 (https://developer.apple.com/library/mac/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObject_Class/#//apple_ref/occ/instp/NSManagedObject/ managedObjectContext) - “如果接收方已从其上下文中删除,则可能为零。” –