Copyright (C) iPhoneアプリ開発備忘録 All rights reserved.
ブログ内で記したコード、内容の正確性は保証いたしません。
記載内容を実装したことにより発生した不具合・損害等の責任は一切負いません。



2012年05月30日

マイグレーション要否判定つきのCore Data 自動マイグレーション



Core Dataの自動マイグレーションは、データモデルが変更されたときの1度だけ行えばよく、マイグレーション処理を通せば、それだけ処理時間がかかる。
これを回避するためには、事前にマイグレーションが必要かどうかを判定すればよい。

[ AppDelegate.m ]

didFinishLaunchingWithOptions
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.

// Migration start
if ([self shouldPerformCoreDataMigration])
{
if ([self performMigration] == NO)
{
__persistentStoreCoordinator = nil;
}
[self persistentStoreCoordinator];
}
// Migration end

MasterViewController *masterViewController = [[[MasterViewController alloc] initWithNibName:@"MasterViewController" bundle:nil] autorelease];
self.navigationController = [[[UINavigationController alloc] initWithRootViewController:masterViewController] autorelease];
masterViewController.managedObjectContext = self.managedObjectContext;
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];

return YES;
}
アプリ起動時、didFinishLaunchingWithOptionsにて、shouldPerformCoreDataMigrationメソッドを軌道してマイグレーションが必要かを判定する。
次にマイグレーションが必要であれば、performMigrationメソッドを呼び出してマイグレーション処理を実行する。マイグレーション実行後、persistentStoreCoordinatorメソッドを通してpersistentStoreCoordinatorインスタンスを作り直す。


managedObjectContext
- (NSManagedObjectContext *)managedObjectContext
{

if (__managedObjectContext != nil) {
return __managedObjectContext;
}

NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; // options = nilで実行(migrationなし)
if (coordinator != nil) {
__managedObjectContext = [[NSManagedObjectContext alloc] init];
[__managedObjectContext setPersistentStoreCoordinator:coordinator];
}

return __managedObjectContext;
}
managedObjectContextはテンプレート(Xcodeで自動生成したクラス)から変更なし。
persistentStoreCoordinatorメソッドが呼び出されたとき、options = nilで実行されるため、マイグレーション処理は行わない。


managedObjectModel
- (NSManagedObjectModel *)managedObjectModel
{
if (__managedObjectModel != nil) {
return __managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"CoreDataMigrationTest" withExtension:@"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

return __managedObjectModel;
}
managedObjectModelはテンプレート(Xcodeで自動生成したクラス)から変更なし。


persistentStoreCoordinator
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
return [self persistentStoreCoordinatorWithOption:nil];
}
persistentStoreCoordinatorは、テンプレートではNSPersistentStoreCoordinator処理の記述を行っているのだが、ここからpersistentStoreCoordinatorWithOptionメソッドを オプション:nilつきで呼び出して実行するように修正する。


persistentStoreCoordinatorWithOption
- (NSPersistentStoreCoordinator *)persistentStoreCoordinatorWithOption:(NSDictionary *)options
{

if (__persistentStoreCoordinator != nil) {
return __persistentStoreCoordinator;
}

NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataMigrationTest.sqlite"];

NSError *error = nil;
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];


if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
NSLog(@"persistentStoreCoordinatorWithOption Unresolved error %@, %@", error, [error userInfo]);
abort();
}

return __persistentStoreCoordinator;

}
persistentStoreCoordinatorWithOption:optionsは、新たに追加するメソッドで、optionsはnilの場合とmigration処理用に設定されている場合の2通りで呼び出される。
persistentStoreCoordinatorインスタンスはここで作られる。optionsにnilが設定されている場合はマイグレーションは行われない。


shouldPerformCoreDataMigration
- (BOOL)shouldPerformCoreDataMigration
{

NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataMigrationTest.sqlite"];

NSError *error = nil;
NSDictionary *storeMetadata = [NSPersistentStoreCoordinator
metadataForPersistentStoreOfType:NSSQLiteStoreType
URL:storeURL
error:&error];

if (storeMetadata == nil)
{
return NO;
} else if (error) {
NSLog(@"Checking migration was failed (%@, %@)", error, [error userInfo]);
abort();
}
BOOL isCompatibile = [[self managedObjectModel]
isConfiguration:nil
compatibleWithStoreMetadata:storeMetadata];

return !isCompatibile;
}
shouldPerformCoreDataMigrationはマイグレーション要否判定処理。
カレントのデータモデルと、保存されているCore Dataとで、整合がとれているかチェックを行い、不整合がある場合はマイグレーションが必要なのでYESを返している。


performMigration
- (BOOL)performMigration
{

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

__persistentStoreCoordinator = nil;
[self persistentStoreCoordinatorWithOption:options];
// NSError *error;
NSError *error = nil;
if (error)
{
//エラー処理
NSLog(@"performMigration error: %@", error);
return NO;
}
return YES;
}
performMigrationはマイグレーション処理の事前処理で、NSDictionary型のoptionsに自動マイグレーションのためのオプションを編集し、persistentStoreCoordinatorWithOptionにこのoptionsを設定して、persistentStoreCoordinatorインスタンスを作る。


参考記事:
http://ken-plus.blogspot.jp/2012/03/core-data-model.html
http://cocoadays.blogspot.jp/2011/02/coredata-coredatamanager.html
http://cocoadays.blogspot.jp/2011/02/iosmac-coredata.html
http://yoo-s.com/topic/detail/381







タグ:iPhone iPAD IOS
posted by mobileDeveloper at 15:01 | Comment(0) | TrackBack(0) | Core Data はてなブックマーク - マイグレーション要否判定つきのCore Data 自動マイグレーション | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバック
Apple、Appleのロゴ、App Store、iPodのロゴ、iTunesは、米国および他国のApple Inc.の登録商標です。
iPhone、iPod touch、iPadはApple Inc.の商標です。
iPhone商標は、アイホン株式会社のライセンスに基づき使用されています。
その他、本ブログに記載されている製品名、会社名は、それぞれ各社の商標または登録商標です。