我希望有人可以解釋爲什麼在釋放源/主機對象時,以下示例中的關聯對象不會自動解除分配。下面的示例代碼有點人爲(道歉提前),但它解釋了我的問題。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) - 「如果接收方已從其上下文中刪除,則可能爲零。」 –