nirasan's tech blog

趣味や仕事の覚え書きです。Linux, Perl, PHP, Ruby, Javascript, Android, Cocos2d-x, Unity などに興味があります。

MagicalRecord を試したメモ

はじめに

  • iOS アプリ開発で ActiveRecord ライクに CoreData を扱うことが出来る MagicalRecord を試したメモ
  • CocoaPod を使うのも初めてなのでそこもちょっと詳しく

動作環境

  • XCode 6.1.1
  • MagicalRecord 2.2
  • mogenerator 1.27

CoreDateの用語

  • 管理オブジェクト(NSManagedObject) : レコード
  • 管理オブジェクトコンテキスト(NSManagedObjectContext) : ORM
  • 管理オブジェクトモデル(NSManagedObjectModel) : スキーマ

プロジェクトの作成

  • "Use Core Data" にチェックを入れて作成

MagicalRecord のインストール

CocoaPod のインストール

  • インストールしていなければ
sudo gem install cocoapods

MagicalRecord のインストール

# cd /path/to/xcode/project
# /usr/bin/pod init
# vi Podfile
target 'ProjectName' do
  pod "MagicalRecord"
  pod "MagicalRecord/Shorthand"
end
# /usr/bin/pod update

MagicalRecord を読み込む

  • pod update によって CocoaPods が有効な状態の XCode プロジェクトファイル(APPNAME.xcworkspace)が生成されているので、これを開く
# open App.xcworkspace
  • CocoaPods のビルドを行う
    • 画面左上の方にあるビルド対象のセレクトボックスをクリックして "New Scheme" を選択
    • "Pods-APPNAME" を選択してビルド対象として作成
    • ビルドデバイスを "iOS Device" に変更し、ビルドを実行

エンティティ(テーブル)の追加

  • APPNAME.xcdatamodeld ファイルを選択
  • "Add Entity" ボタンでエンティティの作成
  • 画面右のインスペクタで Entity の Name と Class を設定 (Class はクラスファイル生成時に必要)
  • エンティティを選択して "Add Attribute" ボタンでアトリビュート(カラム)の作成

リレーションシップについて

  • http://qiita.com/yuiseki/items/33ec35ec99b5304be90a
  • Auther エンティティと Book エンティティが 1:多 の関係になるとする
  • Auther の設定
    • Auther の Relationships で "+" を押下しリレーションシップを作成
      • Relationships を books
      • Destination を Book
      • Inverse はとりあえずそのまま(Book 側の Inverse を設定すれば自動でセットされる)
    • Auther の books を選択した状態のインスペクタで、Relationships の Type を "To Many" に
    • 同じく "Delete Rule" を "Cascade" にすると Auther 削除時に関連する Book も削除されるので任意で設定
  • Book の設定
    • Book の Relationships で "+" を押下しリレーションシップを作成
      • Relationships を auther
      • Destination を Auther
      • Inverse は books
    • Book の auther を選択した状態のインスペクタで、Relationships の Type を "To One" に

カスタム管理オブジェクトクラスの作成

mogenerator のインストール

# brew install mogenerator
# /usr/local/bin/mogenerator -v

ファイルの作成

# /usr/local/bin/mogenerator -m Model.xcdatamodeld/Model.xcdatamodel -O CoreData/ --template-var arc=true

MagicalRecord の初期化

AppDelegate.h

#import <MagicalRecord.h>
#import <MagicalRecord+Setup.h>

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [MagicalRecord setupCoreDataStackWithAutoMigratingSqliteStoreNamed:@"app.db"]; // 追記
    return YES;
}
- (void)applicationWillTerminate:(UIApplication *)application {
    [MagicalRecord cleanUp]; // 追記
}

MagicalRecord を使う

ViewController.h

  • Auther.h, Book.h はカスタム管理オブジェクトクラス
#import <CoreData/CoreData.h>
#import <CoreData+MagicalRecord.h>
#import "Auther.h"
#import "Book.h"

ViewController.m

- (void)viewDidLoad {
    [super viewDidLoad];
    
	// Auther の作成
    Auther* auther = [Auther MR_createEntity];
    auther.name = @"Neal Stephenson";
    
	// Book の作成と Auther との関連付け
    Book* book1 = [Book MR_createEntity];
    book1.title = @"Snow Crash";
    [auther addBooksObject:book1];

    Book* book2 = [Book MR_createEntity];
    book2.title = @"The Diamond Age";
    [auther addBooksObject:book2];

    Book* book3 = [Book MR_createEntity];
    book3.title = @"Cryptonomicon";
    [auther addBooksObject:book3];
	
	// 作成したレコードの登録
    [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
    
	// Auther の一覧を取得
    NSArray* array = [Auther MR_findAll];
    int i = 0;
    NSLog(@"Count:%lu", (unsigned long)[array count]);
    for (Auther* a in array) {
        NSLog(@"#####%d name=%@", i, a.name);
		// Auther に関連付いた Book の取得
        for (Book* b in a.books) {
            NSLog(@"----- title=%@", b.title);
        }
        i++;
    }
	
	// 削除
	[auther MR_deleteEntity];
    [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
}