iCloudの設定を指定ますが、いろいろわからないことばかりです。一応、動いているんです。OSや世代の異なる4台の端末でテストしてもちゃんとデータが同期します。もちろん、1台の端末だったら削除して再度インストールしても削除前のデータがちゃんと表示されます。1台のデータを変えると他のがパコパコ変わりだして楽しいです。
でも、ややこしいことが幾つか。。。とりあえず、今までの顛末をまとめます。
あ、はじめに言っておきます。まだ完全にiCloudを理解していないので、思ったままを書きます。iCloudに挑戦する前の人が読むとわけがわからなくなるかも><
設定してみた編
いろいろ記事はあるんですが、iCloud プログラミング入門を主に参考にして作成しました。他には、多分世界で一番読まれているiOS How-To : Using Core Data with iCloudを参考にしました。
とりあえずわからなかったら検索しつつiCloud プログラミング入門のとおりにやっていけば、動くところまでは行くような気がします。
CoreDataの準備が整う前にデータを利用しようとしてクラッシュする
まぁ上のサイト参考にすれば一応動くんですが、落ちちゃったんです。それは僕のiCloudの理解不足とアプリの仕様に関係しています。僕のアプリは起動直後にCoreDataの読込を行います。上のサイトを参考にしてやったのですが、この部分がうまくいきませんでした。iCloudとCoreDataを連携させた場合、persistentStoreCoordinatorの準備に時間がかかって、CoreDataがすぐに使える状態にはならないのですね。
そこで、とりあえずPrepareViewControllerを作って、それを表示して準備中という画面を出しました。その後、CoreDataの準備が整うとがRefetchAllDatabaseDataという通知が来るという作りになっているので、これが来た時に、ビューを差し替えました。
[UIApplication sharedApplication].keyWindow.rootViewController = self.rootViewController;
こんな感じで差し替えできたんですね。知りませんでした。これで一応問題は解消です。もっと良いやり方ご存知のかた教えて下さい><。
iCloudのデータを削除したい
最初、どうしてもiOS5と同期ができなくてpersistentStoreCoordinatorを生成するあたりの設定をいろいろいじりました。いじった後に、やっぱり戻そうとかなってサーバー側の情報どうなんだろうと気になったら、やっぱりちゃんと削除する方がよいという記事を見つけたので削除してみました。
削除の時に参考にしたのは、CoreData: iCloud同期についての考察 その1です。どのタイミングで削除すればよいか、記事にもあるStackoverflowを読んだのですが、わけわからず自分で適当なメソッドを作りました。
// iCloudのサーバー側の情報を削除する - (void)deleteiCloud { // サーバー側の情報を削除する // applicationWillResignActiveあたりで実行してみると良いかも。 NSURL *cloudURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; if (cloudURL) { // iCloud 用の設定 cloudURL = [cloudURL URLByAppendingPathComponent:@"data"]; } NSError *error; [[NSFileManager defaultManager] removeItemAtURL:cloudURL error:&error]; }
AppDelegate.mのapplicationWillResignActive:に書いてます。流れとしては、通常通りCoreDataが起動してサーバーから更新通知を受け取ったりします。落ち着いたなと思った所で、ホームボタンを押してアプリをバックグラウンドにやる。その時点で上記の処理が行われます。
タイミングだとかコードの正しさだとかわからないのですが、とりあえずこれをやったあとiOS5の同期ができるようになったので効果はあったようです。時間があるときにURLForUbiquityContainerIdentifierとか調べなきゃダメですね。
更新通知が来た時にテーブルをリロードしたい
最初コードの意味がわからなくてリロードできてませんでした。しっかり読むと、どうやら、
- NSPersistentStoreDidImportUbiquitousContentChangesNotificationという通知がiCloudのサーバーから届く。
- その通知が来たらNSManagedObjectContextのmergeChangesFromContextDidSaveNotification:でアプリ内のデータを更新する。
という流れのようでした。なので、2の後にテーブルをリロードするための通知を飛ばしたところ、テーブルの更新に成功しました。
わからないこと
- 設定画面のアプリ名とアイコンの設定方法がわからない。今はどこかでつけた不本意な名前(AppIDかproduct名)になっている。アイコンは表示されていない。
- 設定>iCloud>ストレージとバックアップ>ストレージを管理の書類及びデータに表示される。アプリからすべて削除をしても、iCloudからは消えたように見えるが端末にデータが残る。再度アプリを起動するとちゃんとiCloudにデータが復活する。これでいいのかなぁ。
- 設定>iCloud>ストレージとバックアップ>ストレージを管理の書類及びデータでアプリのデータを削除した後、起動時にSafe save failed for fileというエラーが出るようになった。これはiCloudのバグっぽいです。ちょっと長くなるので次の記事に詳しく書きます。