この数年、Core Dataはローカルでの永続化において、Realmのような他のサービスを好む開発者の間ではかなりひどい評判です。このトークでは、Core Dataを使うことはそんなに悪いことではないと考える理由を説明します。Core Dataでうまくいかないところや、その落とし穴を回避する例をお見せします。また、Core Dataのアプリへの設定についても簡単に説明します。終わりには、みなさんはCore Dataをアプリに安全に統合するのに役立つ簡単なルールを用意することになるでしょう。
今日話す理由ですがCoreDataが好きと人に言うと、なぜ、と言われる、ひどいじゃないか、と言われる。 でもそうではないと思っているのでその理由について説明していきたいと思います。
10年前はたしかにひどかったと思います。
新人のデベロッパの人たちは、複雑、Realmが簡単と聞いてRealmに傾倒する人がいるようですが、そうではない場合もあります。
誰にでも使える良いものだと説得するのが目的ではありません。スタックをどう設定するかをお見せし、データモデルの更新まで、この段階まで行けば状況が見えてくる。そして複数の管理オブジェクトを使うところまで見ていく。
そして最後にパフォーマンス改善まで見ていきます。
使ったことがある人、たくさんコードが出ると思いました?いまは実はこんなに少ないコードでできるんですよ
最初の設定にはこれしかいりません。
モデルエディタを使います、ここには新しい話はありません。
Attributeの名前などを設定する
Relationsihp Inspecta
一つ面白い、クールなフィーチャーがあるので、砂金モデルエディタに追加されたものです。
モデル定義ではダメでサブクラス定義が必要だったと思います。モデルや設定を2箇所で定義するのは良くないと思うが、
エンティティみていただくとコード生成ドロップダウンがある
自分でサブクラスを作らなくても対応してくれる。
気をつけていただきたいのはこのファイルをモディファイしないでください、アプリをビルドするたびにモディファイされてしまいます。
これをアプリにしていきましょう
ほとんどのアプリでは、DBからデータをフェッチすることが必要
fetched results controllerを使う
DataStoreと同期が取れるようにしてくれる
2つほど必要なことがある。fetchリクエスト、何をとってくるべきかプロパティを指定するところ
コアデータが必要なファイルだけをフェッチするようにする。
これが終わればfetched result controller をつくる
2つ目のパラメータはマネージドオブジェクト、ViewContextというものがある、あとで説明する。
3つ目パラメータはTableVeiwのときに使いでがある
fetched resultを分割してくれる。
データが変わればデリゲーションに対して通知をする
データに変更があればcontrollerがそれを把握し、TableViewを更新する。
魔法のような流れになっています。
Delegateの流れは魔法ではなくて機能するように作らなくてはいけません。
willChangeとdidChange
すべてのアップデートはデリゲート側に渡される
tableViewのUpdateに適している
もう一つ、変更があったオブジェクトに対してIndexPathとともに呼び出しがかかる。
ここまで素晴らしいですよね
Datamodelを少しアップデートしたい時があると思う。どうしたら良いでしょう
マイグレーションが必要でしたよね
いままで新しいモデルバージョン作ったりしていましたね
最新ではどうするのでしょう
新しいプロパティを足すと自動でマイグレーション
ただし単純な変更に対してのみ機能します。 追加とか削除とか。
オプショナルにとかはモデルバージョンが必要
テストはしてください。
ここまでは簡単だったと思います。
では複雑になったら?
マルチコンテキスト設定
ViewContext、いくつかのオブジェクトが入っています。
一つ一つのオブジェクトはDBから取得する
ViewContextの良さは、メインスレッドの作業で対応できる、UIに載せられる。
欠点は、なにかFetchするときは大量の場合、UIがブロックされる。
バックグラウンドコンテキストを使ったほうが良い。
ViewContextにはfetched Objectができる。BackgroundContextには
Persistent Contextに入れるとViewContextをアップデートしてくれる
最初の手法はバックグラウンドコンテキストがよく使われるなら。シンプルで早いなら後者で
もう一つ見方を変えましょう。
バックグラウンドコンテキストを使った場合
Parsistent Containerにためます。ViewContextに反映される
これがマルチコンテキストセットアップの作り方です。複雑に見える、難しかったが、簡素化されてきた。 オーバーヘッドが少なくなってきた。
でもよく聞く、批判、パフォーマンス
CoreDataはデータベースです。
スローダウンしてしまう。
うまくいく方法を示していきたい。
まずは分析を行う。Instrumentをつかっていく、デバッグを行っていく。
InstrumentでFetchリクエストを最適化する。
このカンファレンスを例に見ていく。
Instrumentのアップデートです。Fetchリクエストをコアデータに送るとできるだけ小さな処理として実行しようとする。
キャッシュからFetch、キャッシュミスがあればDatabaseから取ってくる
リストの一つのアイテム、3つのDBのクエリが切り分けられて走っている。非常に大きなものなら大変。
どう対応するか、CoreDataはRelationshipが交差するのはよく分かっている。
Prefetchするとどうか
デバッガフラグを有効にする
CoreDataに関するログがでる
4つのクエリが実行されている。
これ以上の情報が欲しい場合
1-4の数値を渡してレベルを変えられる
より多くのアウトプットが得られる
結論としては、CoreDataをアプリの中でスタートするのは非常にシンプル。モデルのアップデートも簡単。マルチプルマネージドオブジェクト、これも比較的簡単に出来るようになった。パフォーマンスは非常に良くなる。ロギング、測定で改良を続けてください。