NSManagedObjectContextの扱いについて考えてみました

NSManagedObjectContextの扱いについて考えてみました – Morizotter Blog「NSManagedObjectContextはどうやって扱えばいいんだ!」ということが自分の中ではっきりせず、結構長い間うだうだしていましたが、今日、がっと調べてある程度自分の中では解消したので、ちょっと自分の理解を書いてみたいと思います。バックグラウンド処理などもありますが、それは別に解説している記事はいろいろあるので、あまり触れず、主にNSManagedObjectContextの使いについて書きます。

Xcodeのひな形から考える

その前に、Xcodeで作成できるひながついて考えてみます。Xcodeでプロジェクトを生成する際に、Master-Detail Applicationを選択して、Core Dataのチェックボックスにチェックを入れれば、とてもシンプルでわかりやすいひな形が作成されます。このひな形について考えてみます。

ここで作成されるNSManagedObjectContextのインスタンスは1つで、AppDelegateに記述されていること、applicationWillTerminate:
にsaveのメソッドがあること(ビューの操作で内容が変わった度にsaveしているにもかかわらず)から考えて、ここで想定されているのはapplicationが起動してから終了するまでのスパンでNSManagedObjectContextのインスタンスを1つ持つということになると思います。

NSManagedObjectContextにNSPersistentStoreCoordinatorがセットされているので、NSManagedObjectContextでsaveを行うと、すぐに保存用のファイル(SQLite)に保存が行われます。

1つだからシンプルとも言えるのですが、ここがいちばんのモワモワポイントだったんです。僕にとっては。それは、

  1. 全データのほんの一部しか更新しないのに、NSManagedObjectContextでデータを展開していると、展開されている全てのデータをチェックしている気がしてなんか気持ち悪い。
  2. saveはNSManagedObjectContext単位で行われるので、すぐに保存しないとsaveのときに保存される箇所がいたるところに発生する可能性がでてきてなんか気持ち悪い。

だいたいこんな感じです。変更した後ですぐに保存したり、ちゃんと管理すればよいとは思うのですが、なんかすっきりしない状態が長く続いていました。DBの概念について僕の理解が足りていないので、別にこれはこれでよいものなのかもしれませんが。

僕のモヤモヤに関連するNSManagedObjectContextの簡単な説明(間違っていたらごめんなさい)

  • saveはNSManagedObjectContext単位。NSManagedObjectは必ず1つのNSManagedObjectContextと紐付いているので、紐付いているNSManagedObjectが全て保存される。
  • persistentStoreCoordinatorがセットされていたらファイルに永続化されるが、parentContextがセットされているとファイルへの永続化は行われず、parentのcontextにマージされるだけ。

保存したい対象だけNSManagedObjectContextで取得して、用を終えたら捨てる

で、今日いろいろ調べている過程で、自分なりにある程度整理できたので簡単に書きます。

  1. メインスレッドにメインのNSManagedObjectContextがいる。アプリケーション起動と同時に生まれて、終了と同時に消える。
  2. 編集をしたいときには、メインのNSManagedObjectContextの子を作り、子が必要なデータを取得して編集する。
  3. 子の変更をメインのNSManagedObjectContextにマージする。
  4. メインのNSManagedObjectが保存処理を行う(SQLiteに永続化、もう一枚バックグラウンドのcontextをかまして永続化等)
  5. メインのNSManagedObjectの変更を検知して色々見た目など変更(NSFetchedResultsControllerは検知がデフォルトなので楽)

長くなりましたが、3,4に関しては、子のsetParentContext:にメインのNSManagedObjectContextをセットしてやれば自動的に行われますし、もちろん、5の通知に関しても勝手に飛びます。

編集が完了したらsaveすればよいし、やっぱやーめたと思ったら、編集用のContextを削除するだけでその他のデータには全く影響を与えません。編集対象の取得はNSManagedObjectIDでやれば楽ちんです。

これでよいのではなかろうか!

実際に利用する際は、バックグラウンド処理などを想定して作成するのでもう少し複雑になりましたが、編集に関しては上記で良い気がします。無駄な処理をしているかもしれませんが、気持ち的には気持ち悪さが消えスッキリしました!

参考にしたのは、次の2つの資料です。いろいろネット上には情報がありますが、結局この2つで必要かつ十分でした!

Multi-Context CoreData最強でした。Core Dataにおける、NSManagedObjectContextについて、これ以上わかりやすく説明されている資料はないのではないかと思います。そして、SlideShareは参考リンクにこちらが載っていたので、この資料をもとにわかりやすくまとめられたのだと思います。このSlideShareを発見してから最強の英語資料に到達したので、ほんとに感謝してます。

他にモワモワしてること

結構大きな謎が解けた(と思われる)。あとは、NSFetchRequestをビューコントローラで作って良いのかなーという問題が残ってます。作って良いですかね。よく使うのは共有できるようにしたりして。今勉強中の、『Learning Core Data for iOS: A Hands-On Guide to Building Core Data Applications』のサンプルにはビューコントローラで作っていました。Xcodeのひな形もそうです。ただ、ビューコントローラが肥えるのかなぁと思ったりして迷ってます。Learning Core Data for iOSは導入なのでわかりやすく説明するためにそういうサンプルにしているのかも。。

どなたかご意見・ご教授いただけるとありがたいし、楽しいです!


You may also like...