我希望有人能解释为什么当源/主机对象被释放时,以下示例中的关联对象不会自动释放。下面的示例代码有些做作(提前道歉),但它解释了我的问题。
该示例假定 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 Managed Object Context (MOC) 将被新的Product
Managed Object (MO) 出售和使用。上面的代码工作正常 - 到目前为止。
然而!如果我将createProduct
函数的前两行组合起来:
let newProduct = CoreDataHelpers.newProduct(context: CoreDataHelpers.vendBackgroundWorkerContext())
然后应用程序将崩溃并try newProduct.managedObjectContext?.save()
带有EXC_BAD_ACCESS
.
乍一看,这似乎有点奇怪——因为我们所做的只是重构了代码。深入研究文档,该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
}
这似乎非常有效 - 直到我签入 Instruments。看起来,当Product
MO 被释放时,现在关联的 MOC 不是(当源对象被释放时不应该自动释放吗?)
我的问题是:有人可以解释阻止它被释放的 MOC 的附加参考在哪里吗?我是否在 MO 和 MOC 之间创建了保留周期?