22
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

MagicalRecordを使う

Last updated at Posted at 2014-11-25

今まであまりCoreData周りのライブラリ使ったことなかったのですが、今回MagicalRecordを利用することになりました。
ライブラリの機能が豊富でドキュメントを見てもわからず、ちょっとずつ異なるメソッド名を見てもどういうときに使うのかわからなかったので調べてみました

前提

NSManagedObjectContext(オブジェクトの管理スペース)のContextType

Method 説明
NSConfinementConcurrencyType スレッド拘束パターン、 コンストラクタにタイプを指定しないで生成した場合のデフォルト
NSPrivateQueueConcurrencyType private dispatch queueを使用する。バッチ処理や永続化処理に向く
NSMainQueueConcurrencyType Main Queueを使用する。Viewの描画が固まってしまうので、大量のデータをこのContextで処理するのは避けるべき

基本的に中規模以上のアプリは、NSManagedObjectContextを複数生成して使用します。
MagicalRecordを使うと、NSManagedObjectContextの生成とPublish/Subscribe(NSNotificationCenterなど)の登録、NSManagedObjectContextへの保存、永続化処理を簡単に行えるようです。

MagicalRecordのsetupメソッドで生成されるNSManagedObjectContext

Context 説明
MR_rootSavingContext
  • persistentStoreCoordinatorが接続されている
  • NSPrivateQueueConcurrencyType
MR_defaultContext
  • ParentContextとして、MR_rootSavingContextを設定
  • NSMainQueueConcurrencyType

ざっくりとした理解だと、MR_rootSavingContextの方はデータの永続化、MR_defaultContextはデータの表示・更新などで利用するような感じです。

保存メソッド

最初に混乱するのが、NSManagedObjectContext (MagicalSaves)MagicalRecord (Actions)の両方に保存メソッドがあることです。

  • NSManagedObjectContext (MagicalSaves)に定義されているメソッドは、NSManagedObjectContextへの保存または永続化処理
  • MagicalRecord (Actions)に定義されているメソッドは、NSManagedObjectContextを新たに生成または取得してNSManagedObjectContext (MagicalSaves)に定義されているメソッドを呼び出している

MagicalRecord (Actions)

やっていることは下のような処理です。

  1. contextを生成
  2. 1.で生成したものをBlocksで渡して、アプリ側でそのContextを使ってデータ作成・更新処理などが行えるコールバック呼び出し
  3. NSManagedObjectContext (MagicalSaves)に定義されているメソッドを呼び出し、データの永続化まで行う

contextの生成・取得はメソッドが自動でやってくれるため、アプリ側ではそのcontextを使ってコールバックに必要なデータの作成・更新の処理を書くだけです。

非同期呼び出し処理タイプ

Method 説明
+ (void)saveWithBlock:(void(^)(NSManagedObjectContext *localContext))block; 下のメソッドをcompletionBlocksがnilで呼び出し
+ (void)saveWithBlock:(void(^)(NSManagedObjectContext *localContext))block completion:(MRSaveCompletionHandler)completion; 親のcontextとしてMR_rootSavingContextを指定して、NSPrivateQueueConcurrencyTypeのcontextを作成します
+ (void)saveUsingCurrentThreadContextWithBlock:(void (^)(NSManagedObjectContext *localContext))block completion:(MRSaveCompletionHandler)completion; Main threadから呼び出したときとそれ以外で作成されるcontextが異なります。ただ、MR_defaultContextを経由するのは変わりません。
  • Main threadから呼び出した時

    • localContext: MR_defaultContextを利用
  • Main thread以外から呼び出した時

    • localContext: Thread毎に作成/登録したcontextを利用(再利用してる?)
    • parentContext: MR_defaultContext(NSMainQueueConcurrencyType)
|

実行完了待ちタイプ

上の実行完了待ちバージョン

  • + (void) saveWithBlockAndWait:(void(^)(NSManagedObjectContext *localContext))block;
  • + (void) saveUsingCurrentThreadContextWithBlockAndWait:(void (^)(NSManagedObjectContext *localContext))block;

NSManagedObjectContext (MagicalSaves)

MagicalRecord (Actions)に定義されたメソッドを利用すると、contextの生成からデータの永続化まで自動で行ってくれますが、それでは困ることがあります。

  1. ローカルの登録フォームからデータを生成したが、APIでサーバーにリクエストを送ったらエラーが返ってきた。
  2. 画面を閉じる前に保存したい(保存タイミングの制御)
  3. 複数のAPIからデータを取得して、全部揃ったタイミングで保存

1.の場合は、サーバーに保存できるまでCoreDataで管理するデータを生成しないという選択肢がありますが、スコープを超えてプリミティブなデータを持っておくのはダルいです。
それよりも、専用のcontextを生成して、サーバーに保存が成功したらローカルに保存・永続化、保存失敗したらcontextごとなかったことにするとかの方が簡単です。

あと、一回一回いちいち永続化するのではなく、一連の処理が完了したら永続化したいところです。

定義されている保存メソッドは下記の通りです。

  • - (void) MR_saveOnlySelfWithCompletion:(MRSaveCompletionHandler)completion;
  • - (void) MR_saveToPersistentStoreWithCompletion:(MRSaveCompletionHandler)completion;
  • - (void) MR_saveOnlySelfAndWait;
  • - (void) MR_saveToPersistentStoreAndWait;
  • - (void) MR_saveWithOptions:(MRSaveContextOptions)mask completion:(MRSaveCompletionHandler)completion;

メソッド名にWaitが入っている場合は、実行完了まで待つタイプで、ToPersistentStoreが入っているのは、ParentContextをさかのぼって保存するタイプです。さかのぼったcontextにpersistentStoreが接続されていれば永続化処理が行われます。
あと、saveOnlySelfが入っているものは、そのcontext自身にのみ保存するタイプです。

上のメソッドは、自分自身のみかルートとなるcontextまでさかのぼって保存するしかないため、
もっと細かく保存するcontextやタイミングを指定したい場合は、MagicalRecordに頼らずに、CoreDataフレームワークで用意されているメソッドを使うしかないです。

ということで、何を調べていたかというと既存の処理が重いのでどのメソッドを実行しているときに重いのかを調査したかっただけです。

22
21
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?