[iOS] CoreData - マイグレーション[5] マイグレーション中にアプリを終了させたらどうなる?

2010年12月14日火曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

[前回] Cocoaの日々: [iOS][Mac] CoreData - マイグレーション[4] モデルファイルの構成

マイグレーションの検証中の素朴な疑問:Core Data のマイグレーション中にアプリを落としたり、電源を落としたりするとどうなるのか?
試してみた。


サンプルプログラム


前回のソースに手を入れて初回起動時に 10,000件のデータを登録するようにしてみた。実行するとデバッグコンソールに 20件毎のコミット状況が書きだされる。
最初にバージョン1のモデルで実行し、次にバージョン2のモデルへ切り替えてマイグレーションが実行されるようにする。

まず最初に正常動作の確認をしたところ次の結果となった。
[バージョン1] サンプルデータ 10,000件の生成: 32秒
[バージョン2] マイグレーション 10,000件  : 24秒
※ iPhone 3GS / iOS 4.2

マイグレーションの開始と終了は NSEntityMigrationPolicy のメソッドを利用してわかるようにした。こんな感じ。
- (BOOL)beginEntityMapping:(NSEntityMapping *)mapping
 manager:(NSMigrationManager *)manager error:(NSError **)error
{
 NSLog(@"Begin migration");
 return YES;
}
- (BOOL)endEntityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager
 error:(NSError **)error
{
 NSLog(@"End migration");
 return YES;
}



アプリ終了


次にマイグレーション実行中にアプリケーションを停止させてみた。ログを見ていると終了後も処理は実行されていてマイグレーションが完了した。どうも自動的にバックグラウンドでマイグレーション処理が継続して実行されているようだ。ちなみにサンプルプログラムはバックグラウンド動作の指定はしていない。UIApplicationExitsOnSuspend は True になっている。


アプリ強制終了


Fast App Switching でアプリを強制終了させても動作し続けていた。うーむ。
※この後は検証していない


電源オフ


マイグレーション実行中にアプリを終了させ、さらに電源をオフにしてみた。しかしこの間もバックグラウンドで動き続けていた。10,000件のデータの場合、処理時間が長いのでバックグラウンドの10秒ルールに抵触して強制終了させられてしまった。
SpringBoard[27] <Warning>: CoreDataMigSamp[1241] has active assertions beyond permitted time:
     {(
         <SBProcessAssertion: 0x5c53d80> identifier: Suspending process: CoreDataMigSamp[1241] 
           permittedBackgroundDuration: 10.000000 reason: suspend owner pid:27 preventSuspend
           preventThrottleDownCPU  preventThrottleDownUI
     )}
SpringBoard[27] <Warning>: Forcing crash report of CoreDataMigSamp[1241]...
SpringBoard[27] <Warning>: Finished crash reporting.
ReportCrash[1258] <Error>: Saved crashreport to /var/mobile/Library/Logs/Cra...
Tcom.apple.launchd[1] <Notice>: (UIKitApplication:com.yourcompany.
  CoreDataMigSample[0x11dc]) Exited: Killed
処理件数 3,000件を試した時にはマイグレーション処理が10秒以内に収まったので、この時は電源オフ後にマイグレーションが完了した。

さて途中で Killされた後、アプリを起動するとどうなるのか。
CoreDataMigSample[1389:307] Removed orphaned, partially migrated store file
 file://localhost/var/mobile/Applications/A7DFB71B-5B24-41D4-A871-
 F2AA18369684/Documents/.CoreDataMigSample.sqlite.migrationdestination_
 41b5a6b5c6e848c462a8480cd24caef3
CoreDataMigSample[1389:307] Begin migration
CoreDataMigSample[1389:307] End migration
前回の失敗が破棄されてマイグレーションが最初から実行され、そして完了した。おお、Core Data すごいぜ。。


考察


Core Data のマイグレーションは1箇所の変更であっても、新DB作成→旧DBからのマイグレーションという手続きを取る(新DBはマイグレーション成功後に正式な名前に替えられて旧DBと置き換わる。旧DBは名前が変更されてバックアップとして残る)。その為に件数が多い場合は時間がかかる。このマイグレーションに時間がかかる場合 iOS デバイスだと途中でアプリを終了させられたり電源を落とされる可能性が高い。それ故、Core Dataを使ったアプリのバージョンアップに関する大きな懸念点の一つとしてずーっと気になっていた。これが今回の検証で不整合が基本的に発生しない作りになっていることが確認できたのは大きい。マイグレーションのバックグラウンド動作は iOS 4.0 からなのかは確認できていないが、少なくとも iOS 4.0以上をターゲットにしたアプリケーションで Core Data を使う場合の懸念材料が一つ減った。機能面と合わせ、運用面での性能も充実してきたので iOSデバイスでも十分に実用に耐えるのではないかと思う。


ソースコード


GitHub からどうぞ。
CoreDataMigSample at 2010-12-14 from xcatsan/iOS-Sample-Code - GitHub


- - - -
後はマイグレーション処理中の経過をユーザへフィードバックできればいいな。後ほど調べてみよう。

Responses

Leave a Response

人気の投稿(過去 30日間)