リリース済みのiPhone/iPadアプリのDBのテーブル定義を変更したい。こんなことって、ありますよね?しかし、サーバサイドのアプリと違って、クライアントサイドで動くiPhone/iPadアプリはどうやってデータの移行をすれば良いのでしょうか?リリース後に気がついて、私は小一時間途方にくれました。
でも、iPhoneなら出来るんです。簡単に!!
正確に言うとApple謹製のDBのフレームワーク、CoreDataを使っていた場合は簡単に移行(マイグレーション)が実現出来ます。
詳しい情報は、次のリンクをご参照ください。
Core Data Model Versioning and Data Migration
Lightweight Migration
簡単な手順としては、次のような形になります。
- 新しいバージョンのモデルを追加する。
- 追加したモデルに、属性(カラム)を追加する。
必要なだけ、追加します。
- マッピングファイルを作成する。
File -> New File -> Core Data -> Mapping Model
マッピングファイルは、Source Data Model(移行元)とTarget Data Model(移行先)を指定します。
注意点としては、どのバージョンからどのバージョンに移行するのかする解るようにすることです。
どういうことかというと、Version1 -> Version2 -> Version3とこちらの期待通りに移行してくれるとは
限らないということです。 Version1 -> Version3といった人もいます。
なので、Version3まである場合は、 ver1->ver3とver2->ver3と2ファイルの用意が必要です。
ファイル名もV1toV2.xcmappingmodel等、一目でわかる形が良いのではないでしょうか?
- 自動マイグレーションコードを追加する。
詳細は、下の方に書いておきます。
- 現在のバージョンを変更する
該当の.xcdatamodeldを選択して、File InspecterのVersioned Core Data ModelのCurrentを変更します。
自動マイグレーションのコード記述
自動マイグレーションで、変換(マイグレーション)が起きるタイミングは、NSpersistentCoordinatorでオプションで変換を付けた時になります。データアクセスクラスみたいなので一元化しておけば、そこの部分にオプション追加するだけで対応が可能になります。
私の場合は、DataManagerという基底クラスを作って、そこで 永続ストアコーディネータの作成やDBファイルの作成を一手に行なっているので、ここだけの修正で済みました。CoreDataを使った開発の詳細は、こちらのエントリーで書いています。
DataManager.m
NSError *error = nil; NSURL *storeURL = <#The URL of a persistent store#>; NSPersistentStoreCoordinator *psc = <#The coordinator#>; NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil]; BOOL success = [psc addPersistentStoreWithType:<#Store type#> configuration:<#Configuration or nil#> URL:storeURL options:options error:&error]; if (!success) { // Handle the error. }
ただ大量データの変換が必要な場合、注意が必要となります。数十件程度のデータであれば、すぐに終わります。が、それが数千件レベルのデータとなりますと、それ相応の時間が必要となります。その場合にアプリ起動時にいきなりマイグレーションが起こると、アプリの起動タイムアウトが発生する可能性があります。またそうではなくても、ユーザは壊れたかと思って中断することも考えられます。その点を考慮した上で、マイグレーションをどこで行うかの設計が必要になります。
最初にiPhoneアプリでDB(SQLite)を使う時に、CoreDataを使うかサードパーティのFMDBを使うか悩みました。FMDBは慣れ親しんだSQL文で操作出来るし、記述量も少なめとかなり魅力的にみえました。一方、Appleのフレームワークの上という所でバージョンアップ時の対応等で継続性の懸念がありました。悩んだ末に、一度はちゃんとCoreDataを使ってみないとダメだろうと思い、CoreDataを採用した経緯があります。今となっては、良かったなぁと思います。正直、開発している段階ではここまで気が回らなかったので、助かりました。これから開発される方は、是非CoreDataをお使いください。
あと、iPhone/iPadアプリを効率的にかつ保守性の高いコードで書くには、是非、木下さんのiOS開発におけるパターンによるオートマティズムをお読みください。CoreDataのサンプルコード等も入手出来て、本当に参考になります。
enjoy!!