iOSアプリのデータ操作はMagical Recordでマジ簡単!:生産性ガチアゲなオープンソースiOSライブラリ(3)(2/2 ページ)
ゼロからiOS SDK開発を始める新規開発者でも超高速・高品質な開発を可能にするオープンソースのライブラリを目的別に紹介していく連載です。実際にライブラリを組み込みながら技術的な側面も併せて詳細に説明していきます。今回は、アップル製O/RマッピングのCoreDataを使いやすくするObjective-Cライブラリについて、概要や使い方を紹介します。
サンプルプログラムの作成
Supporting Files/MagicalRecordSample-Prefix.pch
ここに記述したものは、プロジェクト内全てのソースコードに対してインポートされます。CoreData(MagicalRecord)は、いろいろなクラスで使われることが多いため、ここに追加します。
#import <Availability.h>
#ifndef __IPHONE_3_0
#warning "This project uses features only available in iOS SDK 3.0 and later."
#endif
#ifdef __OBJC__
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
    // #import <CoreData/CoreData.h>を削除し、下記を追加
    #import "CoreData+MagicalRecord.h"
#endif
AppDelegate.m
ここでは、「Cat」を3つ新規追加して、更新、削除を行っています、ソースコードの量がどれほど削減されるか、CoreDataのみ使った場合も記述しました。
#import "AppDelegate.h"
#import "Cat.h"
@implementation AppDelegate
@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // *** 設定 ***
    // 保存方法を指定
    [MagicalRecord setupCoreDataStack];
    
    NSError *error;
    
    [self allDeleteCoreData]; // 全データを消去
    
    // *** Default CoreData ***
    
    // insert
    NSManagedObjectContext *context = [self managedObjectContext];
    Cat *cat1 = [NSEntityDescription insertNewObjectForEntityForName:
                 @"Cat" inManagedObjectContext:context];
    cat1.name = @"mike";
    cat1.age  = [NSNumber numberWithInt: 2];
    Cat *cat2 = [NSEntityDescription insertNewObjectForEntityForName:
                 @"Cat" inManagedObjectContext:context];
    cat2.name = @"tama";
    cat2.age  = [NSNumber numberWithInt: 5];
    Cat* cat3 = [NSEntityDescription insertNewObjectForEntityForName:
                 @"Cat" inManagedObjectContext:context];
    cat3.name = @"tora";
    cat3.age  = [NSNumber numberWithInt: 1];
    
    // update
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:
                                   @"Cat" inManagedObjectContext:context];
    fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:entity];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name = 'tama'"];
    [fetchRequest setPredicate:predicate];
    NSArray *fetchArr = [context executeFetchRequest:fetchRequest error:&error];
    Cat *tama = [fetchArr objectAtIndex:0];
    NSLog(@"tama age : %@", [tama age]);
    tama.age = [NSNumber numberWithInt: 3];
    
    // delete
    [fetchRequest setEntity:entity];
    predicate = [NSPredicate predicateWithFormat:@"name = 'mike'"];
    [fetchRequest setPredicate:predicate];
    fetchArr = [context executeFetchRequest:fetchRequest error:&error];
    Cat *mike = [fetchArr objectAtIndex:0];
    [context deleteObject:mike];
    
    // save
    error = nil;
    if (![context save:&error]) {
        NSLog(@"error = %@", error);
    }
    
    // check
    
    fetchRequest = [[NSFetchRequest alloc]initWithEntityName:@"Cat"];
    error = nil;
    NSArray *all = [context executeFetchRequest:fetchRequest error:&error];
    NSLog(@"all count : %d", [all count]);
    NSLog(@"all : %@", all);
    
    [self allDelete]; // 全データを消去
    
    // *** MagicalRecord ***
    
    NSManagedObjectContext *magicalContext = [NSManagedObjectContext MR_defaultContext];
    
    // insert
    Cat* magicalCat1 = [Cat MR_createEntity];
    magicalCat1.name = @"mike";
    magicalCat1.age  = [NSNumber numberWithInt: 2];
    Cat* magicalCat2 = [Cat MR_createEntity];
    magicalCat2.name = @"tama";
    magicalCat2.age  = [NSNumber numberWithInt: 5];
    Cat* magicalCat3 = [Cat MR_createEntity];
    magicalCat3.name = @"tora";
    magicalCat3.age  = [NSNumber numberWithInt: 1];
    
    // update
    Cat *magicalTama = [Cat MR_findFirstWithPredicate:
                        [NSPredicate predicateWithFormat:@"name = 'tama'"]];
    NSLog(@"magicalTama age : %@", [magicalTama age]);
    magicalTama.age = [NSNumber numberWithInt: 3];
    
    // delete
    Cat *magicalMike = [Cat MR_findFirstWithPredicate:
                        [NSPredicate predicateWithFormat:@"name = 'mike'"]];
    [magicalMike MR_deleteEntity];
    
    // save
    [magicalContext MR_saveOnlySelfAndWait];
    
    // check
    
    NSArray *magicalAll = [Cat MR_findAll];
    
    NSLog(@"magicalAll count : %d", [magicalAll count]);
    NSLog(@"magicalAll : %@", magicalAll);
    return YES;
}
- (void) allDeleteCoreData
{
    NSManagedObjectContext *context = [self managedObjectContext];
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]initWithEntityName:@"Cat"];
    NSError *error = nil;
    NSArray *all = [context executeFetchRequest:fetchRequest error:&error];
    int len = [all count];
    for ( int i = 0 ; i < len ; i++ ) {
        Cat *cat = [all objectAtIndex:i];
        [context deleteObject:cat];
    }
    error = nil;
    if (![context save:&error]) {
        NSLog(@"error = %@", error);
    }
}
- (void) allDelete
{
    NSArray *all = [Cat MR_findAll];
    int len = [all count];
    for ( int i = 0 ; i < len ; i++ ) {
        Cat *cat = [all objectAtIndex:i];
        [cat MR_deleteEntity];
    }
}
- (void)applicationWillResignActive:(UIApplication *)application
{
...
サンプルの実行結果
ここまででプログラムの変更は完了です。では実行してみましょう。
データ内容を見ると同じものが表示されているので成功です。
以上がMagicalRecordのシンプルな使い方です。今回もサンプルコードをGitHubにて公開しているので、ぜひ試してCoreDataとお友達になってみてください!!
Rails風に利用できる軽量ライブラリ「Objective-Record」も
冒頭でも書いた通り、CoreDataはiOSでデータを利用する際の一般的な手法ですが、利用方法に癖があり、人によっては習得するのに時間がかかる可能性があります。そういった懸念点をOSSライブラリで解消するのも現代の開発手法として浸透しても良いと思います。コスト削減だけではなく、ソースが簡略化されて可読性が上がるので非常にお勧めです。
CoreData関連では他にもRuby on Rails風に利用できる軽量ライブラリ「Objective-Record」などもありますので、自分のスタイルに合ったものを見つけてください。
次回はOSSライブラリでのネットワーク接続とログ収集について紹介します。
著者プロフィール
川崎 順平(かわさき じゅんぺい)
株式会社ソニックス スマートデバイスソリューション事業部 コンサルティンググループ
コンサルティング業務として、モバイルファースト開発ガイドラインやテストガイドラインの作成を行いながら、日々各スマートデバイス向けアプリケーションの開発に従事。Windowsストアアプリ開発コミュニティ「Windows 8 Developers」もやってます。
平川 裕多(ひらかわ ゆうた)
株式会社ソニックス スマートデバイスソリューション事業部
板前から転身したエンジニア。iOS開発歴3年。今は自社クラウドサービス「Scirocco Cloud」の開発を日々行っています。趣味は醤油工場めぐり。
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- 連載「iOS SDKで始めるObjective-C入門」最新記事一覧
Windowsを使っていたけど、iOSアプリを作るためにMacを使い始めた初心者を対象に、開発ツールXcode/iOS SDKを使ってiPhone/iPadアプリを作る方法を、プログラミング言語「Objective-C」の書き方/文法を交えて解説 - Objective-C初心者のためのiOS SDKコード例一覧〜iPhone/iPadアプリ開発者が知らないと損するまとめ
iOS SDKを使った@ITのアプリ開発記事のAPIコード例へのリンク集。メソッドやクラスなどの使い方のご参考に - iPhone/iPadスマートアプリ開発レシピ
スマートフォンの「スマート」は、さまざまなセンサやハードウェアを使うところにある。本連載で、さまざまなセンサやハードウェアを使うiOS(iPhone、iPad、iPod touch)のスマートなアプリを作ってみよう - iOSでジオ(GEO)プログミラング入門
iPhone/iPad/iPod touchで動く位置情報アプリを作成するための「測位機能の取り扱い」「地図の取り扱い」「サーバとの通信」という重要なポイントを解説します - SDKで始めるiPad/iPhoneアプリ開発の勘所
初めてiPhone/iPadアプリ開発に挑戦する人が、迷わず短時間でアプリを作れるように、数多くの情報の中から要点をグっと絞った開発の勘所を紹介する入門連載です - iOSアプリ開発入門
盛り上がるiOS(iPhone・iPad・iPod touch)アプリ開発。そのハウツーや魅力に関する@IT記事一覧です 
