ユーザーが選択した情報、ディスク保存したデータのメタ情報などを保存するのにCore Dataが利用できます。
Xcode 4.2ではSingle View Appplicationを選択してプロジェクト作成するとCore Dataを使用する設定が追加されないので、既存プロジェクトにCore Dataを追加します。
参照: Core Data Model Editor Help
- Data Model追加
Xcodeのメニューから File > New > New File... を選択。
テンプレート選択ウインドウで iOS > Core Data > Data Model を選択。
xcdatamodelファイルを保存。
- Entity追加(DBのTableに相当)
Xcode左ペインでプロジェクト名をクリック。
Xcode左ペインで追加されたxcdatamodelファイルを選択。
Xcode下ペインの+Add Entityをクリック。
追加された"Entity"の名前を変更。
- attribute追加(DBのITEMに相当)
Attibutesグループの下側ツールバーの+をクリック。
追加された"Attribute"の名前を変更。
データ型を選択。
必要に応じてPropertyを設定。
- NSManagedObjectのサブクラス追加
Xcodeのメニューから Editor > Create Managed Object Subclass... を選択。
ファイルの追加または置換を行うEntityを選択。
既存ファイルがある場合は置換になるので注意。
- framework追加
ビルド前にCoreData.frameforkをリンクに追加します。
Appleのチュートリアルではアプリケーションデリゲートクラスに次の property、methodを追加します。
@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (NSURL *)applicationDocumentsDirectory;
- (void)saveContext;
複数のNSManagedObjectContextインスタンスが保持する状態は異なる場合があるので、マルチスレッドでCore Dataを扱うような場合は注意が必要です。同じデータの異なる状態を異なるContextで持つような状況が避けらればよいのですが、さもなければ対策が必要になります。Core Dataでは楽観的ロック(Optimistic Lock)によりsave:時に元データに変更があった場合に対処する方法、notificationにより他のcontextで変更されたときに通知を受け取り、データを最新状態にする方法が用意されています。
実装例
MYAppDelegate.h
#import <CoreData/CoreData.h>
@interface IDAppDelegate : UIResponder <UIApplicationDelegate>
@property (nonatomic, strong, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, strong, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, strong, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@end
MYAppDelegate.m
@implementation IDAppDelegate
@synthesize managedObjectContext = _managedObjectContext;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
@synthesize managedObjectModel = _managedObjectModel;
//保存先ディレクトリ
- (NSString *)applicationDocumentsDirectory {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
//_persistentStoreCoordinatorがnilなら作って返す。
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (_persistentStoreCoordinator == nil) {
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]
initWithManagedObjectModel:[self managedObjectModel]];
NSURL *url = [NSURL fileURLWithPath:[[self applicationDocumentsDirectory]
stringByAppendingPathComponent: @"CoreData.sqlite"]];
NSError *error = nil;
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:url
options:nil error:&error])
{
//エラー処理
NSLog(@"persistentStoreCoordinator: Error %@, %@", error, [error userInfo]);
}
}
return _persistentStoreCoordinator;
}
//_managedObjectModelがnilなら作って返す。
-(NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel == nil) {
_managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
}
return _managedObjectModel;
}
//_managedObjectContextがnilなら作って返す。
- (NSManagedObjectContext *)managedObjectContext {
if (_managedObjectContext == nil) {
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
}
return _managedObjectContext;
}
//_managedObjectContextのデータを保存する。
- (void)saveContext {
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
//エラー処理
NSLog(@"saveContext: %@", error.debugDescription);
}
}
//アプリケーション終了時に保存
- (void)applicationWillTerminate:(UIApplication *)application
{
[self saveContext];
}
//バックグランド移行時に保存
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[self saveContext];
}
//メモリ警告時に保存、リセット
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
[self saveContext];
[[self managedObjectContext] reset];
}
@end
開発中に項目の追加/削除があると古いデータを読み込めなくなります。
Core Data 自動マイグレーションを設定することをお勧めします。
Core Data 自動マイグレーション
core data modelの不要なバージョンを削除する方法