NSManagedObjectContextクラス
2011. 04. 09
●概要
NSManagedObjectContextのインスタンスは、単一の『オブジェクト空間』またはアプリケーション内のスクラッチパッドを表します。
その主な責任は、管理オブジェクトのコレクションの管理です。
これらのオブジェクトは、一つ以上の永続ストアの内部で一貫したビューを表す、関連したモデルオブジェクトのグループを形成します。
単一の管理オブジェクトのインスタンスは、一つのコンテキストに一つだけ存在しますが、オブジェクトの複数のコピーは異なるコンテキストに存在することができます。
したがってオブジェクトをユニークにするには、特定のコンテキストにスコープします。
ライフサイクルの管理
コンテキストは管理オブジェクトのライフサイクルにおいて中心的な役割を果たす強力なオブジェクトで、アンドゥ/リドゥや逆関係処理、ライフサイクル管理から(フォールティングを含む)検証の責任を持ちます。
コンテキストを介して永続ストアからオブジェクトを取得または『フェッチ』することができ、これらのオブジェクトに変更を加え、そしてどちらかを破棄して(再びコンテキストを介して)永続ストアに戻り、変更またはコミットを適用します。
コンテキストはオブジェクトの変更を監視とアンドゥマネージャを保持する責任があり、アンドゥとリドゥをきめ細かく制御することができます。
オブジェクトの新規挿入や削除はフェッチで行うことで永続ストアに変更をコミットすることができます。
永続ストアコーディネータ
コンテキストは常に、データを含む様々な永続ストアへのモデルとディスパッチ要求を提供する、『親』永続ストアコーディネータを持っています。
コーディネータが無ければ、コンテキストは完全に機能しません。
コンテキストのコーディネータは管理オブジェクトモデルを提供し、永続性を処理します。
外部ストアからフェッチされた全てのオブジェクトは、外部ストアに各オブジェクトを一意に識別するために使用するグローバルな識別子(NSManagedObjectIDのインスタンス)と共にコンテキストに登録されます。
通知
コンテキストは様々な時点で通知を投稿します。
(例えばNSManagedObjectContextObjectsDidChangeNotificationなど)
通常、既知のコンテキストからのみこれらの通知を受け取るように登録する必要があります。
いくつかのシステムフレームワークでは、内部的にCore Dataを使用してください。
(addObserver...メソッドへオブジェクトのパラメータとしてnilを渡すことによって)全てのコンテキストからこれらの通知を受け取ろうと登録する場合、処理が困難な場合は予想外の通知を受け取る可能性があります。
同一性
Core Dataはスレッド(またはシリアライズされたキュー)を使用して、管理オブジェクトと管理オブジェクトコンテキストを保護します。
(『Concurrency with Core Data』を参照)
この結果は、デフォルトのオーナーが割り当てられたスレッドまたはキューであることを仮定しています。
(これはinitメソッドを呼び出したスレッドによって決定されます)
したがって、初期化を行ったスレッドとは異なるスレッドにコンテキストを渡さないでください。
代わりに、受け取るスレッド/キューに新しいコンテキストを生成し、永続ストアコーディネータへの参照を渡す必要があります。
NSOperationを使用する場合は、(一連のキュー用の)メインまたは(共存するキュー用の)スタート内にコンテキストを生成する必要があります。
サブクラス化の注意
NSManagedObjectContextのサブクラス化は強く推奨しません。
変更の追跡とアンドゥの管理メカニズムは高度に最適化されており、故に複雑かつ繊細になっています。
独自に追加されたロジックを介在させると予期せぬ結果を生み出し、processPendingChangesに影響を与える可能性があります。
ストアの移行などの状況では、Core Dataは自身が使用するためにNSManagedObjectContextのインスタンスを生成します。
このような状況下では、カスタマイズしたサブクラスの機能に依存することはありません。
どのNSManagedObjectのサブクラスでも、(NSManagedObjectContextのサブクラスとしてではなく)常にNSManagedObjectContextと完全な互換性がある必要があります。
●タスク
オブジェクトの登録とフェッチ
– executeFetchRequest:error:
– countForFetchRequest:error:
– objectRegisteredForID:
– objectWithID:
– existingObjectWithID:error:
– registeredObjects
管理オブジェクトの管理
– insertObject:
– deleteObject:
– assignObject:toPersistentStore:
– obtainPermanentIDsForObjects:error:
– detectConflictsForObject:
– refreshObject:mergeChanges:
– processPendingChanges
– insertedObjects
– updatedObjects
– deletedObjects
別のコンテキストからの合成変更
– mergeChangesFromContextDidSaveNotification:
アンドゥ管理
– undoManager
– setUndoManager:
– undo
– redo
– reset
– rollback
– save:
– hasChanges
ロック
– lock
– unlock
– tryLock
削除の伝播
– propagatesDeletesAtEndOfEvent
– setPropagatesDeletesAtEndOfEvent:
登録されたオブジェクトの保持
– retainsRegisteredObjects
– setRetainsRegisteredObjects:
永続ストアコーディネータの管理
– persistentStoreCoordinator
– setPersistentStoreCoordinator:
失効間隔の管理
– stalenessInterval
– setStalenessInterval:
マージポリシーの管理
– mergePolicy
– setMergePolicy:
●インスタンスメソッド
・executeFetchRequest:error:
- (NSArray *)executeFetchRequest:(NSFetchRequest *)request error:(NSError **)error
与えたフェッチ要求によって指定された基準を満たす、オブジェクトの配列を返します。
戻り値は、レシーバの永続ストアコーディネータに関連付けされた永続ストアから、レシーバからフェッチされた要求によって指定された基準を満たすオブジェクトです。
エラーが発生した場合はnilを返します。
リクエストで指定された基準に一致するオブジェクトが無かった場合は、空の配列を返します。
返されたオブジェクトは、レシーバに登録されます。
考慮すべき重要な点は以下の通りです。
いくつかのオブジェクトをフェッチする場合は、それらを一緒に処理し、新しいインスタンスの取得または既存のオブジェクトのデータ更新はしないで(現在のインメモリの状態を持つ既存のオブジェクトを取得し)、それからそれらのオブジェクトのスーパーセットを含む新しいフェッチを実行してください。
request:フェッチの検索基準を指定するフェッチ要求を指定します。
error:フェッチを実行して問題があった場合に、問題を説明するNSErrorのインスタンスを含めて返します。
・hasChanges
- (BOOL)hasChanges
レシーバの変更がコミットされていないかを示すブール値を返します。
戻り値は、レシーバの変更がコミットされていない場合はYES、そうでない場合はNOを返します。
Mac OS X v10.6以降では、このプロパティはキー値監視に準拠しています。
(『Key-Value Observing Programming Guide』参照)
Mac OS X v10.6より前では、このプロパティはキー値監視に準拠しておらず、例えばCocoaバインディングを使用している場合、管理オブジェクトコンテキストのhasChangeプロパティへバインドすることはできません。
キー値監視(KVO)を使用してこのプロパティを監視する場合、コンテキストに触れないようにするか、または通知のためにobserveValueForKeyPath:ofObject:change:context:の実装でそのオブジェクトを含める必要があります。
(これはKVO通知のロケーションが複雑なためで、例えばコンテキストはアンドゥの操作やマージの競合を修復している途中の可能性があるからです)
hasChangesの値が変化した結果として、その変更された管理オブジェクトのコンテキストへメッセージを送信する場合は、その後でコールスタックをアンワインドする必要があります。
(通常、performSelector:withObject:afterDelay:または類似したメソッドを使用します)
・persistentStoreCoordinator
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
レシーバの永続ストアコーディネータを返します。
・save:
- (BOOL)save:(NSError **)error
永続ストアへ登録されたオブジェクトへの未保存の変更をコミットしようと試みます。
戻り値は、保存が成功した場合はYES、それ以外はNOを返します。
(例えば、いくつかの編集されたオブジェクトが検証に失敗した場合など)複数のエラーが発生した場合、複数のエラーが示されたNSErrorの記述が返され、userInfo辞書にキーNSDetailedErrorsが含まれます。
NSDetailedErrorsキーに関連付けられた値は、個々のNSErrorオブジェクトを含む配列です。
error:NSErrorオブジェクトへのポインタです。
NSErrorオブジェクトを生成する必要はありません。
NULLを渡した場合、最初の失敗の後に保存処理が中断します。
・setPersistentStoreCoordinator:
- (void)setPersistentStoreCoordinator:(NSPersistentStoreCoordinator *)coordinator
レシーバの永続ストアコーディネータを設定します。
コーディネータは管理オブジェクトモデルの提供し、永続性を処理します。
複数のコンテキストがコーディネータを共有できることに注意してください。
coordinatorがnilの場合、このメソッドは例外を発生させます。
永続ストアコーディネータからコンテキストを『切断』する場合、単純にコンテキストへの全ての参照を解放するだけでなく、正常に割り当てを解除する必要があります。
coordinator:レシーバの永続ストアコーディネータ
●定数
●通知
参考文献
・NSManagedObjectContext Class Reference
NSManagedObjectContextのインスタンスは、単一の『オブジェクト空間』またはアプリケーション内のスクラッチパッドを表します。
その主な責任は、管理オブジェクトのコレクションの管理です。
これらのオブジェクトは、一つ以上の永続ストアの内部で一貫したビューを表す、関連したモデルオブジェクトのグループを形成します。
単一の管理オブジェクトのインスタンスは、一つのコンテキストに一つだけ存在しますが、オブジェクトの複数のコピーは異なるコンテキストに存在することができます。
したがってオブジェクトをユニークにするには、特定のコンテキストにスコープします。
ライフサイクルの管理
コンテキストは管理オブジェクトのライフサイクルにおいて中心的な役割を果たす強力なオブジェクトで、アンドゥ/リドゥや逆関係処理、ライフサイクル管理から(フォールティングを含む)検証の責任を持ちます。
コンテキストを介して永続ストアからオブジェクトを取得または『フェッチ』することができ、これらのオブジェクトに変更を加え、そしてどちらかを破棄して(再びコンテキストを介して)永続ストアに戻り、変更またはコミットを適用します。
コンテキストはオブジェクトの変更を監視とアンドゥマネージャを保持する責任があり、アンドゥとリドゥをきめ細かく制御することができます。
オブジェクトの新規挿入や削除はフェッチで行うことで永続ストアに変更をコミットすることができます。
永続ストアコーディネータ
コンテキストは常に、データを含む様々な永続ストアへのモデルとディスパッチ要求を提供する、『親』永続ストアコーディネータを持っています。
コーディネータが無ければ、コンテキストは完全に機能しません。
コンテキストのコーディネータは管理オブジェクトモデルを提供し、永続性を処理します。
外部ストアからフェッチされた全てのオブジェクトは、外部ストアに各オブジェクトを一意に識別するために使用するグローバルな識別子(NSManagedObjectIDのインスタンス)と共にコンテキストに登録されます。
通知
コンテキストは様々な時点で通知を投稿します。
(例えばNSManagedObjectContextObjectsDidChangeNotificationなど)
通常、既知のコンテキストからのみこれらの通知を受け取るように登録する必要があります。
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(<#Selector name#>)
name:NSManagedObjectContextDidSaveNotification
object:<#A managed object context#>];
selector:@selector(<#Selector name#>)
name:NSManagedObjectContextDidSaveNotification
object:<#A managed object context#>];
いくつかのシステムフレームワークでは、内部的にCore Dataを使用してください。
(addObserver...メソッドへオブジェクトのパラメータとしてnilを渡すことによって)全てのコンテキストからこれらの通知を受け取ろうと登録する場合、処理が困難な場合は予想外の通知を受け取る可能性があります。
同一性
Core Dataはスレッド(またはシリアライズされたキュー)を使用して、管理オブジェクトと管理オブジェクトコンテキストを保護します。
(『Concurrency with Core Data』を参照)
この結果は、デフォルトのオーナーが割り当てられたスレッドまたはキューであることを仮定しています。
(これはinitメソッドを呼び出したスレッドによって決定されます)
したがって、初期化を行ったスレッドとは異なるスレッドにコンテキストを渡さないでください。
代わりに、受け取るスレッド/キューに新しいコンテキストを生成し、永続ストアコーディネータへの参照を渡す必要があります。
NSOperationを使用する場合は、(一連のキュー用の)メインまたは(共存するキュー用の)スタート内にコンテキストを生成する必要があります。
サブクラス化の注意
NSManagedObjectContextのサブクラス化は強く推奨しません。
変更の追跡とアンドゥの管理メカニズムは高度に最適化されており、故に複雑かつ繊細になっています。
独自に追加されたロジックを介在させると予期せぬ結果を生み出し、processPendingChangesに影響を与える可能性があります。
ストアの移行などの状況では、Core Dataは自身が使用するためにNSManagedObjectContextのインスタンスを生成します。
このような状況下では、カスタマイズしたサブクラスの機能に依存することはありません。
どのNSManagedObjectのサブクラスでも、(NSManagedObjectContextのサブクラスとしてではなく)常にNSManagedObjectContextと完全な互換性がある必要があります。
●タスク
オブジェクトの登録とフェッチ
– executeFetchRequest:error:
– countForFetchRequest:error:
– objectRegisteredForID:
– objectWithID:
– existingObjectWithID:error:
– registeredObjects
管理オブジェクトの管理
– insertObject:
– deleteObject:
– assignObject:toPersistentStore:
– obtainPermanentIDsForObjects:error:
– detectConflictsForObject:
– refreshObject:mergeChanges:
– processPendingChanges
– insertedObjects
– updatedObjects
– deletedObjects
別のコンテキストからの合成変更
– mergeChangesFromContextDidSaveNotification:
アンドゥ管理
– undoManager
– setUndoManager:
– undo
– redo
– reset
– rollback
– save:
– hasChanges
ロック
– lock
– unlock
– tryLock
削除の伝播
– propagatesDeletesAtEndOfEvent
– setPropagatesDeletesAtEndOfEvent:
登録されたオブジェクトの保持
– retainsRegisteredObjects
– setRetainsRegisteredObjects:
永続ストアコーディネータの管理
– persistentStoreCoordinator
– setPersistentStoreCoordinator:
失効間隔の管理
– stalenessInterval
– setStalenessInterval:
マージポリシーの管理
– mergePolicy
– setMergePolicy:
●インスタンスメソッド
・executeFetchRequest:error:
- (NSArray *)executeFetchRequest:(NSFetchRequest *)request error:(NSError **)error
与えたフェッチ要求によって指定された基準を満たす、オブジェクトの配列を返します。
戻り値は、レシーバの永続ストアコーディネータに関連付けされた永続ストアから、レシーバからフェッチされた要求によって指定された基準を満たすオブジェクトです。
エラーが発生した場合はnilを返します。
リクエストで指定された基準に一致するオブジェクトが無かった場合は、空の配列を返します。
返されたオブジェクトは、レシーバに登録されます。
考慮すべき重要な点は以下の通りです。
- フェッチ要求に述語が無い場合、指定されたエンティティの全てのインスタンスを取得し、以下の基準に従います。
- (リクエストによって指定されたエンティティのインスタンスで、もしあるならリクエストの述語と一致する)requestによって指定された基準を満たし、コンテキストに挿入されているが永続ストアにまだ保存されていないオブジェクトは、フェッチ要求がコンテキスト上で実行された場合に取得されます。
- コンテキスト内のオブジェクトが変更されている場合、永続ストア内の現在の状態に対してではなく、述語は変更された状態と比較して評価します。
したがって、コンテキスト内のオブジェクトがフェッチ要求の基準を満たすように変更されていた場合、リクエストはたとえ変更がストアに保存されていない場合でも、基準を満たしていないストア内の値を取得します。
逆に、コンテキスト内のオブジェクトがフェッチ要求と一致しないように変更されていた場合、フェッチ要求はストア内のバージョンと一致していても取得しません。 - オブジェクトがコンテキストから削除されている場合、フェッチ要求はたとえその削除がストアに保存されていなくても、取得しません。
いくつかのオブジェクトをフェッチする場合は、それらを一緒に処理し、新しいインスタンスの取得または既存のオブジェクトのデータ更新はしないで(現在のインメモリの状態を持つ既存のオブジェクトを取得し)、それからそれらのオブジェクトのスーパーセットを含む新しいフェッチを実行してください。
request:フェッチの検索基準を指定するフェッチ要求を指定します。
error:フェッチを実行して問題があった場合に、問題を説明するNSErrorのインスタンスを含めて返します。
・hasChanges
- (BOOL)hasChanges
レシーバの変更がコミットされていないかを示すブール値を返します。
戻り値は、レシーバの変更がコミットされていない場合はYES、そうでない場合はNOを返します。
Mac OS X v10.6以降では、このプロパティはキー値監視に準拠しています。
(『Key-Value Observing Programming Guide』参照)
Mac OS X v10.6より前では、このプロパティはキー値監視に準拠しておらず、例えばCocoaバインディングを使用している場合、管理オブジェクトコンテキストのhasChangeプロパティへバインドすることはできません。
キー値監視(KVO)を使用してこのプロパティを監視する場合、コンテキストに触れないようにするか、または通知のためにobserveValueForKeyPath:ofObject:change:context:の実装でそのオブジェクトを含める必要があります。
(これはKVO通知のロケーションが複雑なためで、例えばコンテキストはアンドゥの操作やマージの競合を修復している途中の可能性があるからです)
hasChangesの値が変化した結果として、その変更された管理オブジェクトのコンテキストへメッセージを送信する場合は、その後でコールスタックをアンワインドする必要があります。
(通常、performSelector:withObject:afterDelay:または類似したメソッドを使用します)
・persistentStoreCoordinator
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
レシーバの永続ストアコーディネータを返します。
・save:
- (BOOL)save:(NSError **)error
永続ストアへ登録されたオブジェクトへの未保存の変更をコミットしようと試みます。
戻り値は、保存が成功した場合はYES、それ以外はNOを返します。
(例えば、いくつかの編集されたオブジェクトが検証に失敗した場合など)複数のエラーが発生した場合、複数のエラーが示されたNSErrorの記述が返され、userInfo辞書にキーNSDetailedErrorsが含まれます。
NSDetailedErrorsキーに関連付けられた値は、個々のNSErrorオブジェクトを含む配列です。
error:NSErrorオブジェクトへのポインタです。
NSErrorオブジェクトを生成する必要はありません。
NULLを渡した場合、最初の失敗の後に保存処理が中断します。
・setPersistentStoreCoordinator:
- (void)setPersistentStoreCoordinator:(NSPersistentStoreCoordinator *)coordinator
レシーバの永続ストアコーディネータを設定します。
コーディネータは管理オブジェクトモデルの提供し、永続性を処理します。
複数のコンテキストがコーディネータを共有できることに注意してください。
coordinatorがnilの場合、このメソッドは例外を発生させます。
永続ストアコーディネータからコンテキストを『切断』する場合、単純にコンテキストへの全ての参照を解放するだけでなく、正常に割り当てを解除する必要があります。
coordinator:レシーバの永続ストアコーディネータ
●定数
●通知
参考文献
・NSManagedObjectContext Class Reference