MagicalRecordでCoreDataをお手軽に使う

iOSアプリでデータを保存(serialize/deserialize)する方法としてCoreDataがありますが、コード量が多く慣れるまでにも時間がかかります。

ここではより簡単なMagicalRecordによって、CoreDataを使ってみます。

MagicalRecordActive Recordパターンを採用したCoreDataのラッパーです。ActiveRecordは、Martin FowlerらのPatterns of Enterprise Application Architectureで名付けられ、Ruby on Railsで普及しました。

MagicalRecordがあれば、Webアプリ開発者でもCoreDataを簡単に扱えるようになり、iOSアプリ開発がより身近に感じられるようになると思います。

前提

CocoaPodsはインストール済みとします。CocoaPodsのインストール方法は以下を参照してください。

iOSアプリのプロジェクト作成

  1. Xcodeを開いて新規プロジェクトを作成します。

     File > New > Project
    
    • Use Core Dataの指定は不要です。
      • 指定すると不要なコードが生成されるため、指定しない事をおすすめします。

MagicalRecordのインストール

  1. Podfile作成

    1. .xcodeprojがあるディレクトリにPodfileファイルを作成します。
    2. Podfileに次の1行を追記します。

      pod 'MagicalRecord'

  2. MagicalRecordインストール

    1. ターミナル上でPodfileと同じディレクトリに移動して以下を実行します。

       pod install
      
  3. 設定

    1. アプリ名/アプリ名-Prefix.pchを開いて次の1行を追記します。

       #import "CoreData+MagicalRecord.h"
      

CoreDataデータモデルの定義と作成

  1. Data Modelを追加

    1. メニューからFile > New > File > Data Modelを選択します。
    2. Model.xcdatamodeldを作成します。
  2. Entityを追加

    1. ツリー上でModel.xcdatamodeldを選択します。
    2. Add EntityをクリックしてEntityを追加します。
    3. Entityを適切な名前に変更します。
    4. Entityの属性(Attributes)や関係(Relationship)を定義します。
  3. Entityから必要なソースコードを自動生成

    1. ツリー上でModel.xcdatamodeldを選択します。
    2. メニューからEditor > Create NSManagedObject Subclass > Next > Next > Createを選択します。

      Use scalar properties for priitive data typesをチェックすると以下のようなスカラー型(定数型)のプロパティがプリミティブなデータ型に変換されます。チェック不要で構いません。

      • Date -> NSTimeInterval.
      • Double -> double.
      • Float -> float.
      • Integer 16/32/64 -> int16_t/int32_t/int64_t
      • Boolean -> BOOL

MagicalRecordの起動/終了処理

  1. 起動処理

    AppDelegete.mファイルを開いてdidFinishLaunchingWithOptionsに起動処理を追加します。

     - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
     {
         // 以下を追加
         [MagicalRecord setupCoreDataStackWithAutoMigratingSqliteStoreNamed:@"database_name.sqlite"];
         return YES;
     }
    

    初期化には以下のようなメソッドが用意されています。目的に応じて選択します。

    ローカルのSQLite

     + (void) setupCoreDataStack;
     + (void) setupAutoMigratingCoreDataStack;
     + (void) setupCoreDataStackWithInMemoryStore;
     + (void) setupCoreDataStackWithStoreNamed:(NSString *)storeName;
     + (void) setupCoreDataStackWithAutoMigratingSqliteStoreNamed:(NSString *)storeName;
    

    iCloud

     + (void) setupCoreDataStackWithiCloudContainer:(NSString *)icloudBucket localStoreNamed:(NSString *)localStore;
     + (void) setupCoreDataStackWithiCloudContainer:(NSString *)containerID contentNameKey:(NSString *)contentNameKey localStoreNamed:(NSString *)localStoreName cloudStorePathComponent:(NSString *)pathSubcomponent;
     + (void) setupCoreDataStackWithiCloudContainer:(NSString *)containerID contentNameKey:(NSString *)contentNameKey localStoreNamed:(NSString *)localStoreName cloudStorePathComponent:(NSString *)pathSubcomponent completion:(void(^)(void))completion;
    
  2. 終了処理

    AppDelegete.mファイルを開いてapplicationWillTerminateに終了処理を追加します。

     - (void)applicationWillTerminate:(UIApplication *)application
     {
         // 以下を追加
         [MagicalRecord cleanUp];
     }
    

MagicalRecordでのデータ保存

  • 同期

      Album *album = [Album MR_createEntity];
      album.title = @"Friends";
          :
    
      [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
    

MR_saveメソッドは次期メジャーリリースの3.0からは無くなるので同じ機能を持つMR_saveToPersistentStoreAndWaitを使いましょう。

  • 非同期

      Album *album = [Album MR_createEntity];
      [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext){
    
          //保存前の処理(保存したいインスタンスの作成など)
          Album *localAlbum = [album MR_inContext:localContext];
          localAlbum.title = @"NeverMind";
              :
    
      } completion:^(BOOL success, NSError *error) {
    
          //保存後の処理(全件取得や件数カウントなど)
    
      }];
    
  • その他

    MagicalRecord / Docs / Saving.md

MagicalRecordでのデータ取得

  • 全件取得

      NSArray *albums = [Album findAll];
    
  • 条件を指定して取得

      NSArray *albums = [Album MR_findByAttribute:@"genre" withValue:@"piano trio" andOrderBy:@"year" ascending:YES];
    
  • その他高度な取得

    MagicalRecord / Docs / Fetching.md

MagicalRecordでのデータ更新

  • データ取得&更新

    あらかじめAlbumのインスタンス(ここではcheckyourhead)を取得しておきます。

      Album *checkyourhead = ...;
      checkyourhead.rate = [NSNumber numberWithInt:5];
      [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
    

MagicalRecordでのデータ削除

  • 全件削除

      [Album MR_truncateAll];
      [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
    
  • 1件削除

    あらかじめAlbumのインスタンス(ここではmellowgold)を取得しておきます。

      Album *mellowgold = ...;
      [mellowgold MR_deleteEntity];
    

MagicalRecordでのデータカウント

  • カウント

      NSNumber *count = [Album MR_numberOfEntities];
    

注意

MagicalRecordでデータの保存、更新、削除を反映する際は必ず以下を実行します。

    [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];

以上です。MagicalRecordを使うとCoreDataを簡単に扱えます。