ACAccount
s はスレッドセーフではありません。それらが発生したスレッドでのみ使用する必要があります。この目的のために、「スレッド」を「キュー」と読むことができます。
私はそれに関する正式なドキュメントを見たことはありませんがNSLog
、アカウントを持っている場合は、それがコア データ オブジェクトであり、コア データ オブジェクトのスレッド セーフの欠如が十分に文書化されていることがわかります。
具体的な動作は、Core Data オブジェクトが障害になる可能性があるということです。つまり、保持しているのはオブジェクトへの参照であり、実際のオブジェクトではありません。プロパティにアクセスしようとすると、オブジェクトがメモリに読み込まれます。
その下で Core Data が行っていることは、オブジェクトが実際に必要であることがわかるまで、メモリ内に物事をキャッシュし、エラーを返すことです。そのキャッシュの効率的な調整により、オブジェクトを調整する Core Data オブジェクトの個々のインスタンスが 1 つのスレッドに制限されます。
オブジェクトをメモリに入れるアクションを間違ったスレッドで実行した場合 (これは、identifier
ここにアクセスしたときに発生することです)、動作は未定義です。結果が得られるnil
か、アプリケーションがクラッシュする可能性があります。
(余談: コア データがこのように機能する理由は、オブジェクト グラフが格納されているため、おそらく数千の相互接続されたオブジェクトであり、他のオブジェクトのグループと同じようにトラバースできます。ただし、通常はコストを支払いたくありません。使用する情報の小さなサブセットにアクセスするためだけに、それらのすべてをメモリにロードすることに関連しているため、遅延ロード中に通常のObjective-Cインターフェースを提供する方法が必要です)
リンクしたコードは、キュー ホッピングの前に、オブジェクトがキャッシュ内にあり、したがってメモリ内にあることを確認することで、その問題を回避します。したがって、「ストアからのフェッチ」ステップは正しいキューで発生します。ただし、 Core Data が適用しようとしているロジックに応じて、オブジェクトがメモリ内からフォールトに戻る可能性があるため、コードは完全に安全ではありません。
著者は明らかに、Apple 側で何らかのバグを発見したと考えています。彼らはそうではなく、スレッドセーフではないものをスレッドセーフであると想定し、テストでたまたま機能した未定義の動作に依存する方法を見つけただけです。
話の教訓: アカウント自体を 1 つのスレッドに保持します。アカウントのプロパティで何らかの処理を行いたい場合は、関連するプロパティ自体を基本的な Foundation オブジェクトとして収集し、それらをポストします。