CoreDateとは
- Modelオブジェクトをファイルに保存したり、ファイルから復元したりする
- アーカイブよりも多機能
- Modelオブジェクトの変更履歴(アンドゥとレドゥ、オブジェクト間の相互関係の管理)
- Modelオブジェクトのサブセットだけをメモリ内の保持する事ができる
- GUIベースのエディタでModelクラスを定義する事ができる
- データストアのバージョン管理および移行のためのインフラストラクチャ
登場人物
- 管理オブジェクト(Managed Object Model)
- NSManagedObjectまたはNSManagedObjectのサブクラス
- 概念的にはデータベースのテーブル内のレコードオブジェクト
- MVCのModelオブジェクト
- 管理オブジェクトコンテキスト(Managed Ojbject Context)
- NSManagedObjectContextのインスタンス
- 管理オブジェクトのコレクションを管理
- Modelオブジェクトのグループを形成
- ライフサイクル管理、妥当性検証、関係の管理、アンドゥ/リドゥまで管理
- 管理オブジェクトモデル
- NSManagedObjectModelのインスタンス
- データベースを定義するスキーマオブジェクト
- モデルはエンティティ記述オブジェクトのコレクション
- 永続ストアコーディネータ
- 永続ストアコーディネータはNSPersistentStoreCoordinatorのインスタンス
- 永続オブジェクトストア(外部ストア:ファイルなどを指す)のコレクションを管理
- アプリケーション内のオブジェクトとデータベース内のレコードをマッピングする
サンプル
AppleのDeveloper Libraryにあるドキュメントをもとに使ってみる
プロジェクトの作成
プロジェクトの作成の作成じに、Core Dataを使用するにチェックを入れる (Use Core Data for storage)
// 管理オブジェクトコンテキスト
@property (nonatomic, retain, readonly) NSManagedObjectContext
*managedObjectContext;
// 管理オブジェクトモデル
@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
// 永続ストアコーディネータ
@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator
*persistentStoreCoordinator;
- (NSURL *)applicationDocumentsDirectory;
- (void)saveContext;
- Core Dataのモデル(.xcdatamodeld)ファイル(通常、管理オブジェクトモデルと呼ばれる)
データのモデリング
xcodeで[プロジェクト名].xcdatamodelを選択後、Entityを追加、そのEntityに対してAttributeを追加していく
カスタム管理クラスオブジェクト
通常のクラスファイルを作成する手順で「Managed Object Class」を選択
Entityが選択できるので、先ほど作成したEntityを選択する
プロパティはsynthesizedではなく、dynamicとなる。コンパイル時ではなく、実行時にアクセサーを生成する
実装ファイル(Event.m)にはdeallocがない。オブジェクトのライフサイクルはCoreDataが行うため
管理クラスオブジェクトの生成/保存
通常は、NSEntityDescriptionの簡易メソッド(insertNewObjectForEntityForName:inManagedObjectContext:)を使用して管理オブジェクトを作成
指定したエンティティーに対応するクラスを初期化し、コンテキストに挿入する
オブジェクトを追加したり変更したりすると、その変更はsave:が呼び出されるまではメモリ内に保持される
// Eventエンティティの新規インスタンスを作成して設定する
Event *event = (Event *)[NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:managedObjectContext];
// ここでeventに対してデータを設定
// データの保存
NSError *error = nil;
if (![managedObjectContext save:&error]) {
// エラーを処理する
}
管理オブジェクトのフェッチ
フェッチ要求では、最低限、関心のあるエンティティを指定
オブジェクトが持つ値に関する制限を指定したり、オブジェクトを返す順番を指定したりすることも可能
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event"
inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
// ソート
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:@"creationDate" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor,
nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortDescriptor release];
// 実行
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[managedObjectContext
executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil) {
// エラーを処理する
}
[self setEventsArray:mutableFetchResults];
[mutableFetchResults release];
[request release];
管理オブジェクトの削除
レコードを削除するには、NSManagedObjectContextのdeleteObject:メソッドを使用する
登録同様にseveメソッドを読んで、反映させる
// 指定のインデックスパスにある管理オブジェクトを削除する。
NSManagedObject *eventToDelete = [eventsArray
objectAtIndex:indexPath.row];
[managedObjectContext deleteObject:eventToDelete];
// 変更をコミットする。
NSError *error = nil;
if (![managedObjectContext save:&error]) {
はじめてのCoreDataではまりどころ
"The operation couldn’t be completed. (Cocoa error 134100.)"
スキーマを変更する場合、マイグレーション処理をしましょうってことらしい。
アプリを削除して再度実行すればなおる