次の例の関連オブジェクトが、ソース/ホストオブジェクトの割り当てが解除されたときに自動的に割り当てが解除されない理由を説明できます。以下のこのコード例は、を工夫して(前もって申し訳ありません)ですが、私の問題を説明しています。NSManagedObjectContextの割り当て解除の問題 - (Swift | Associated Objects)
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管理オブジェクトコンテキスト:
の例では、文字列属性sku
とXcodeのテンプレートが提供するデフォルトCoreDataスタックでCoreDataエンティティProduct
を前提としてい(MOC)は、新しいProduct
管理オブジェクト(MO)によって販売され、使用されます。このコードは正しく動作しています。
ただし、私はcreateProduct
関数の最初の2行を組み合わせた場合、そのようなこと:
let newProduct = CoreDataHelpers.newProduct(context: CoreDataHelpers.vendBackgroundWorkerContext())
は、アプリが
EXC_BAD_ACCESS
で
try newProduct.managedObjectContext?.save()
でクラッシュします。
これはちょっと変わったように見えます。私たちがしたのはコードをリファクタリングしたものです。 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
}
これは、私がInstrumentsにチェックインするまで、素晴らしいことです。 (ソースオブジェクトの割り当てが解除されたときに、それが自動的に解放すべきではない?)Product
MOが割り当て解除されたときに、今、関連するMOCがでないように思われる
私の質問は次のとおりです。 は、誰かが説明することができますどこの追加参照それが割り当て解除されないようにするMOCにありますか?私はMOとMOCの間に維持サイクルを作りましたか?
オンデマンドでワーカーコンテキストを破棄/作成しないでください。例えば。変更されている2つのMOはまだ保持されていません。同じ文脈であれば、保存は両方のMOに保存されます - あなたはそのうちの1つを永続させたいかもしれません)。複数のワーカーコンテキストを販売する注目すべき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) - "受信者がそのコンテキストから削除された場合はゼロになることがあります。" –