NSManagedObjectContext解除分配问题-(Swift关联对象)
我希望有人能解释为什么在源/主机对象解除分配时,以下示例中的关联对象不会自动解除分配。下面的示例代码有点做作(提前道歉),但它解释了我的问题NSManagedObjectContext解除分配问题-(Swift关联对象),swift,core-data,associated-object,Swift,Core Data,Associated Object,我希望有人能解释为什么在源/主机对象解除分配时,以下示例中的关联对象不会自动解除分配。下面的示例代码有点做作(提前道歉),但它解释了我的问题 该示例假定CoreData实体产品,具有字符串属性sku,并且默认CoreData堆栈由Xcode模板提供: import UIKit import CoreData class ViewController: UIViewController { @IBAction func createProduct(sender: AnyObject)
该示例假定CoreData实体
产品
,具有字符串属性sku
,并且默认CoreData堆栈由Xcode模板提供:
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
功能时,新的Product
托管对象(MO)将出售并使用新的PrivateQueueConcurrencyType托管对象上下文(MOC)。到目前为止,上述代码工作正常
然而!如果我将createProduct
函数的前两行组合在一起,则:
let newProduct = CoreDataHelpers.newProduct(context: CoreDataHelpers.vendBackgroundWorkerContext())
然后应用程序将在使用EXC\u BAD\u访问权限尝试newProduct.managedObjectContext?.save()
时崩溃
乍一看,这似乎有点奇怪——因为我们所做的只是重构代码。深入到中,managedObjectContext
属性被声明为无主(不安全)
。这可能意味着创建的MOC已被解除分配,我们有一个悬空的指针(如果我的假设是错误的,请纠正我)
为了确保MOC不会被解除分配,我尝试将其与MO本身关联<代码>新产品
:
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
}
这似乎工作得很好-直到我检查仪器。当产品
MO被解除分配时,现在关联的MOC不会被解除分配(当源对象被解除分配时,它不应该被自动解除分配吗?)
我的问题是:
有人能解释一下,额外的参考是指阻止其被解除分配的主运行中心吗?我是否在MO和MOC之间创建了保留周期?
您可能正在创建一个循环所有权(保留周期) 每个托管对象都属于托管上下文(上下文拥有该对象),将上下文设置为关联对象意味着该对象现在也拥有该上下文 因此,它们不会被解除分配
真正的解决方案是将背景上下文保存到本地属性,这与使用
mainContext
时所做的相同。为什么不应按需销毁/创建工作上下文?两个正在更改但尚未持久化的MOs。如果在同一上下文中,保存将同时保留两个MOs(您可能只想保留其中一个)。值得注意的CD堆栈出售多个工作上下文(例如)。@SoOverIt如果你是对的,我已经删除了我答案的最后一部分。但是,您仍然必须确保对正在使用的任何托管上下文都有强引用。您提到“每个托管对象都由托管上下文拥有”。这并不完全正确。您仍然可以拥有已删除上下文的托管对象。请参阅NSManagedObject类引用()中有关managedObjectContext的文档-“如果接收器已从其上下文中删除,则可能为零。”@soovrit是的,但托管对象将变得不可用。你不能再保存它并从中读取数据了。非常正确。它确实变得无法使用了。这就是为什么我希望托管对象上下文保持不变。