背景
最近、個人的なiOSアプリ開発でParseを使っている。Parseでは、Local Datastore(ローカルデータストア)という便利そうな機能が以前から発表されており、気になっていた。
そして先月やっと、iOS向けのParseSDKに組み込まれたようだ。試しに使ってみたので、簡単な使い方と使ってみた結果を共有する。
注意事項
Parse Local Datastoreは簡単に使えてとても便利な機能なのだが
挙動に致命的な問題があったため、現時点での利用は見送った。
問題点の内容は後述しているので、参考にしてほしい。
改善されたSDKバージョンのリリースが確認されたときは、この記事にも反映する予定。
確認バージョン: ParseSDK 1.6.1 (iOS向け)
Parse Local Datastore とは
Local Datastoreは、Parseがクラウドに保持しているDBの内容を、アプリローカルのデータベースにも保存して使える機能。
iOSアプリだと、sqliteのデータとして保存される。
ローカルにクラウドのデータを保存できるとどんな嬉しい事があるかは、次のページで詳しく解説されている。
クラウド同期アプリが手軽に作れるかも Parse Local Datastore for iOSがやっと出た | うめのんブログ
基本的な使い方
ローカルデータストアを利用するのに難しい設定は必要ない。
既存のコードに2, 3行追加するだけで恩恵を受けられるようになる。
1.ローカルデータストアの有効化
AppDelegate.mのdidFinishLaunchingWithOptions:
内で設定する。
setApplicationId:
の 「前に」 有効化が必要。
有効化をしないと、ローカルデータストアにアクセスしようとした時にエラーになる。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[Parse enableLocalDatastore]; // 1.ローカルデータストアを有効に
[Parse setApplicationId:PARSE_APP_ID clientKey:PARSE_CLIENT_KEY];
// (略)
return YES;
}
2.ローカルに保存する
PFObjectに対して、pinで始まるメソッドを実行すればそれだけでローカルに保存してくれる。
[object pinInBackground]; // ローカルに保存
NSArray中のPFObjectもまとめて保存することができる。
たとえば取得してきたオブジェクトのリストに対して、pinAllObjectsInBackground:
が使えた。
// PFQueryでクラウドからオブジェクトを取得
PFQuery *query = [PFUser query];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
[PFObject pinAllObjectsInBackground:objects]; // ローカルに保存
}];
3.ローカルから検索する
PFQueryに対してfromLocalDatastore
を指定してやると、ローカルデータストアから検索できる。
それ以外については、普段のPFQueryの使い方と変わらない。
PFQuery *query = [PFUser query];
[query fromLocalDatastore]; // ローカルデータストアからの検索を指定
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// ローカルからの検索結果を利用
}];
問題点
ローカルデータストアの使い方はとても簡単だった。
かなり便利に使えそうである。
使えそうなのだが、現時点だと大きな問題点があったので記述しておく。
ローカルへの保存が、メインスレッドで処理される
なんてこった/(^o^)\
pinAllInBackgroundのようにInBackgroundを指定するメソッドであっても、バックグラウンド処理してくれてない。
完全にUIスレッドを止めてしまっている。
ローカルデータストアに書き込みをしている最中は、アプリが操作不能になってしまった。
仕方がないので、書き込み処理は別スレッドで処理しよう。
処理が遅すぎる
そしてこれが致命的だった。
ローカルデータストア周りの処理が致命的に遅い。
保存も、読み込みも両方だ。
試しに、読み込みにかかる時間を測ってみた。
処理速度の測定
以下のコードで、データの読み込みにどの程度時間がかかるかを測った。
実行環境: iPod touch 第5世代
PFQuery *query = [Comment query];
[query fromLocalDatastore]; // ローカルに保存した分のみ
NSLog(@"start fetch");
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
NSLog(@"finish fetch %d records", objects.count);
}];
ローカルの処理なのに2秒もかかる!
2015-01-04 21:15:50.448 Sample[1523:60b] start fetch
2015-01-04 21:15:52.658 Sample[1523:60b] finish fetch 100 records
え?
ネットワーク越しの処理じゃないのに?
ローカルのDBから読み込んでるだけなのにそんなにかかるの?
しかも...
キャッシュが効いていないと(?)0レコードでも5秒以上かかる
実行タイミングに依っては、5秒以上かかることもあった。
原因は分からないが、DBでのキャッシュの有無の違いからだろうか?
同じクエリを複数回投げると、2回目からは2秒程度になった。
2015-01-04 21:15:19.890 Sample[1523:60b] start fetch
2015-01-04 21:15:24.935 Sample[1523:60b] finish fetch 0 records
なにかこの速度を改善できるような方法がないか探したが
今のところ対策が見つかっていない。
次のリリースで改善されれば良いのだが…。
まとめ
- ローカルデータストアのAPI自体はめちゃめちゃ使いやすい。数行加えるだけで利用可能。
ただ、
- 実行速度が致命的に遅い。読み込みに2秒以上かかる。
よって、
現時点ではこの問題点が改善されるまでは使えない...という判断。
参考
Parse Local Datastore for iOS | Parse Blog
http://blog.parse.com/2014/12/09/parse-local-datastore-for-ios/
Parse iOS SDK Reference
http://parse.com/docs/ios/api/
クラウド同期アプリが手軽に作れるかも Parse Local Datastore for iOSがやっと出た | うめのんブログ
http://umenon.com/2014/12/10/parselocaldatastoreforios/