この場合は、アプリのリリース当初からCore Dataにデータをバンドルしておくのが望ましい。
2012年11月26日に執筆した手法では、現時点で実行時にエラーとなりクラッシュしてしまうので、新たな手法を公開する。
http://iphone-app-developer.seesaa.net/article/303905394.html?1409835494
手順としては下記のようになる。
1. iPhoneシミュレータでCore Dataにデータをインポートするアプリを実行し、Mac上にCore Dataファイルを作成する。仮に、作成されたファイル名を「DataModel.sqlite」、データモデルを「DataModel.xcdatamodeld」とする。
2. Xcodeを起動して新しいプロジェクトに、上記1.で作成したsqliteファイルをコピーする。
ファイルは下記記事で示すフォルダにある。
http://iphone-app-developer.seesaa.net/article/301338657.html
3. 上記2.でコピーしたファイルをリネームする。
変更前:DataModel.sqlite
変更後:DefaultData.sqlite
4. 上記2.で新たに作ったプロジェクト上に上記1.で作成したデータモデルをコピーする。
5. 上記2.で新たに作ったプロジェクト上の、もとからあったデータモデル(hoge.xcdatamodeld)を削除し、上記4.でコピーしたデータモデルの名前をもとからあったデータモデルにリネームする。
変更前:DataModel.xcdatamodeld
変更後:hoge.xcdatamodeld
6. 上記5.のデータモデルを選択した状態で、ファイルメニュー→Editor→Add Model Version... を選択し、新しいバージョンのデータモデルを作る。
7. 古いバージョンを削除してデータモデルは1つのみ存在する状態にする。
(1) 新しいバージョンのデータモデルを作ると下記のような階層になる。
hoge.xcdatamodeld
hoge 2.xcdatamodel ←左側に緑のチェックマークが現在(Current)のバージョンを示す
hoge.xcdatamodel
(2) データモデルの最上位階層の hoge.xcdatamodeld を選択した状態にして、採用したいデータモデルを決めて、Xcodeの右側のInspectorからCurrent Versionを設定する。
上記の場合、hoge 2.xcdatamodel も hoge.xcdatamodel も同一内容のため、どちらを選択してもよいが、当初のバージョンが、Add Model Version して作ったデータモデルというのもおかしいので、hoge.xcdatamodel をCurrent Versionに設定する。
(3) データモデルの最上位階層の hoge.xcdatamodeld を選択して、ファイルメニュー→Edit→Deleteで、Remove Reference Onlyとして削除する。
(4) Finderでプロジェクトファイルを開き、hoge.xcdatamodeld を選択、右クリックして「Show Package Contents」を選択する。
(5) (4)で開いたパッケージ上には、2つのデータモデルがあるので、不要なデータモデル(Current Versionでないデータモデル)を削除する。
hoge 2.xcdatamodel ← Current Versionではない(削除するデータモデル)
hoge.xcdatamodel ← Current Version
(6) 上記1.で作成したデータモデルを再びコピーする。
(7) コピーしたデータモデルをリネームする。
変更前:DataModel.xcdatamodeld
変更後:hoge.xcdatamodeld
8. AppDelegete.mを修正する。
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeUrlFirst = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"hoge.sqlite"];
NSString *storePath = [storeUrlFirst path];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:storePath]) {
NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"DefaultData" ofType:@"sqlite"];
if (defaultStorePath) {
[fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];
}
}
NSURL *storeURL = [NSURL fileURLWithPath:storePath];
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
abort();
}
return _persistentStoreCoordinator;
}
上記コードでは、作成するCore Dataファイルはsqliteで「DataModel.sqlite」としているが、「DefaultData.sqlite」があれば、このファイルを読む込む処理を記述している。
- (NSManagedObjectModel *)managedObjectModel メソッド、- (NSURL *)applicationDocumentsDirectory メソッドは変更不要。
上記7.(7)で、再度コピーしたデータモデルが、バージョン管理されたデータモデルである.xcdatamodeld とはならず .xcdatamodel となる場合がある。
この場合は、うまくいっていないのでやむをえず、新規で作成したプロジェクトを当初はCore Data作成用のプロジェクトとして作成、iPhoneシミュレータで実行し、出来上がったsqliteファイルを同一プロジェクトにコピーして、プロジェクトそのものを開発用として作り替える手法をとるやり方でもいい。
参考記事:
http://www.kuma-de.com/blog/2012-09-27/4092
http://stackoverflow.com/questions/3908836/iphone-add-core-data-to-existing-project
http://stackoverflow.com/questions/7708392/how-to-delete-an-old-unused-data-model-version-in-xcode-4