Core Data モデルに Departments と Employees という 2 つのエンティティがあるとします。
Department は Employees と 1 対多の関係にあります。
次の ManagedObjectContexts があります:
- ルート: 永続ストア コーディネーターに接続されてい
ます - メイン: 親ルートを持つコンテキスト
Employee を作成したいときは、次のようにします。
- Main コンテキストに Department があります
- Main コンテキストに Employee を作成します
- Department を Employee の department プロパティに割り当てます -
Main コンテキスト
を保存します -ルート コンテキスト
これにより、Main コンテキストと Root コンテキストの両方で保持サイクルが作成されます。
refreshObject:mergeChanges
子コンテキストなしで (すべてルート コンテキストで) これを行った場合、Employeeを呼び出して保持サイクルを中断できます。2 つのコンテキストがある私の状況では、そのメソッドを使用してメイン コンテキストのサイクルを中断することはできますが、ルート コンテキストのサイクルを中断するにはどうすればよいでしょうか?
補足:これは私の問題を説明する簡単な例です。Instruments では、割り当て数が増えていることがはっきりとわかります。私のアプリでは、保存しているコンテキストごとに保持サイクルを持つ新しいエンティティ割り当てを取得するため、1 レベルよりも深いコンテキストがあり、さらに大きな問題を引き起こしています。
Update 15/04: NSPrivateQueueConcurrencyType と NSMainQueueConcurrencyType
両方のコンテキストを保存した後refreshObject:mergeChanges
、Main コンテキストで Department オブジェクトを使用して実行できます。これにより、予想どおり、Department オブジェクトが再フォールトし、保持サイクルが中断され、そのコンテキストで Department および Employee エンティティの割り当てが解除されます。
次のステップは、ルート コンテキストに存在する保持サイクルを断ち切ることです (メイン コンテキストを保存すると、エンティティがルート コンテキストに伝播されます)。ここで同じトリックを実行しrefreshObject:mergeChanges
て、ルート コンテキストで Department オブジェクトを使用できます。
奇妙なこと: これは、ルート コンテキストが NSMainQueueConcurrencyType で作成された場合 (すべての割り当てが再フォールトされ、解放された場合) は正常に機能しますが、ルート コンテキストが NSPrivateQueueConcurrencyType で作成された場合は機能しません (すべての割り当ては再フォールトされましたが、解放されていません)。 )。
補足: ルート コンテキストのすべての操作は、 performBlock(AndWait) 呼び出しで行われます
2004 年 15 月更新: パート 2 NSPrivateQueueConcurrencyType
を使用してルート コンテキストで別の (変更がないため役に立たない) 保存またはロールバックを行うと、オブジェクトの割り当てが解除されたように見えます。これが NSMainQueueConcurrencyType と同じように動作しない理由がわかりません。
Update 16/04: デモ プロジェクト デモ プロジェクト
を作成しました: http://codegazer.com/code/CoreDataTest.zip
2004 年 21 月更新: 行き方
Jody Hagings さん、ご協力ありがとうございます。ManagedObjectメソッド
から移動しようとしています。refreshObject:mergeChanges
didSave
次の違いを説明していただけますか。
[rootContext performBlock:^{
[rootContext save:nil];
for (NSManagedObject *mo in rootContext.registeredObjects)
[rootContext refreshObject:mo mergeChanges:NO];
}];
と
[rootContext performBlock:^{
[rootContext save:nil];
[rootContext performBlock:^{
for (NSManagedObject *mo in rootContext.registeredObjects)
[rootContext refreshObject:mo mergeChanges:NO];
}];
}];
上のものはオブジェクトの割り当てを解除しませんが、下のものは割り当てを解除します。