【特集】

TigerのCocoaにみるMVCの完成 - スマートなデータモデルを実現するCore Data

11 管理対象オブジェクトのライフタイム

    木下誠  [2005/10/31]

    これで管理対象オブジェクトを利用するためのクラスは出そろった。続いて、オブジェクトを作成、編集するための手順を説明しよう。管理対象オブジェクトは、通常のオブジェクトは違う方法で初期化して、保持する必要がある。

    Core Dataのための初期化

    アプリケーションでCore Dataを利用するには、まず、管理対象オブジェクトモデル、永続ストアコーディネータ、管理対象オブジェクトコンテキストを用意する必要がある。

    管理対象オブジェクトモデルには、アプリケーションで扱うエンティティをすべて読み込ませる。通常、エンティティは.xcdatamodelファイルに記述してあるので、これを読み込むことになる。永続ストアコーディネータは、ファイルへの書き込みを行うものなので、ファイルを指定して初期化する。管理対象オブジェクトコンテキストは、この永続ストアコーディネータを指定して初期化する。

    開発時には、これらの初期化はテンプレートで用意されるコード内で行われる。これで、Core Dataを利用する舞台が整ったことになる。

    オブジェクトの作成、削除

    では、いよいよ管理対象オブジェクトモデルを作ってみよう。

    まず、エンティティを取り出す。エンティティは、NSEntityDescriptioinというクラスで表現される。管理対象オブジェクトモデルから、このクラスを取り出すことができる。NSEntityDescirptionは、対応する管理対象オブジェクトクラスの名前を持っている。

    これが、目的となる管理対象オブジェクトだ。このクラスをインスタンス化する。この初期化時に、管理対象オブジェクトコンテキストを指定することになる。これで、管理対象オブジェクトをコンテキストに挿入できる。

    この一連の流れは、次のようなコードになる。

    // 名前を指定して、エンティティを表すNSEntityDescriptionを取得
    NSEntityDescription* entity = [[managedObjectModel entitiesByName] objectForKey:@"Mail"];

    // 管理対象オブジェクトのクラスを取得
    NSString* className = [entity managedObjectClassName];
    Class klass = [[NSBundle mainBundle] classNamed:className];

    // エンティティとコンテキストを指定して、管理対象オブジェクトのインスタンスを作成
    // 管理対象オブジェクトはコンテキストに保持されるので、autoreleaseする
    NSManagedObject* object = [[klass alloc] initWithEntity:entity insertIntoManagedObjectContext:context];
    [object autorelease];

    また、これらのことをまとめて処理してくれるメソッドもある。実際には、こちらを使うことになるだろう。NSEntityeDescriptionのクラスメソッドである、insertNewObjectForEntityName:inManagedObjectContext:だ。エンティティ名とコンテキストさえ指定すれば、管理対象オブジェクトのインスタンスを作ってくれる。

    NSManagedObject* object = [NSEntityDescription insertNewObjectForEntityName:@"Mail" inManagedObjectContext:context];

    作成したオブジェクトを削除したいときは、管理対象オブジェクトコンテキストのdeleteObject:メソッドを使う。管理対象オブジェクトは、コンテキストに登録されるので、そちらから削除をすることになる。

    オブジェクトの取り出し

    作成した管理対象オブジェクトは、すべてコンテキストに登録される。では、取り出すときはどうするのか?これは、オブジェクトを指定するリクエストを作成して、それに適合するオブジェクトの集合をとりだすことになる。つまり、これはデータベースでいうところの、クエリーである。

    オブジェクトを指定するには、文字列で式を記述する。具体的には、次のような式や演算子が使える。

    • エンティティがMailのオブジェクトをすべて取り出す(エンティティの指定)
      後述するNSFetchRequestのsetEntity:メソッドを使う。
    • エンティティがMailで、fromがSteveであるものを取り出す(比較演算)
      from == "Steve"
    • エンティティがMailで、fromに"Apple"を含むものを取り出す(contains演算)
      from contains "Apple"
    • エンティティがMailで、fromかtoに"Mac"を含むものを取り出す(論理演算)
      (from contains "Mac") OR (to contains "Mac")
    • エンティティがMailで、MailBoxのnameが"New"であるものに含まれているものを取り出す(関連)
      mailBox.name == "New"

    このような式で、オブジェクトを取り出すのである。

    リクエストを作成するには、NSFetchRequestクラスを、式の指定にはNSPredicateクラスを使う。たとえば、Appleからのメールを取り出すリクエストは、次のように作成する。

    // NSFetchRequestをインスタンス化する
    NSFetchRequest* request = [[NSFetchRequest alloc] init];
    // 取り出すエンティティを設定する
    [request setEntity:[NSEntityDescription entityForName:@"Mail" inManagedObjectContext:context];
    // NSPredicateを使って、式を設定する
    [request setPredicate:[NSPredicate predicateWithFormat:@"from contains 'Apple'"]];

    このようにして作成したリクエストは、コンテキストに対して送る。結果は、オブジェクトの配列の形で受け取ることができる。

    // コンテキストにリクエストを送る
    NSArray* results = [context executeFetchRequest:request error:&error];

    オブジェクトの保存

    オブジェクトは、管理対象オブジェクトコンテキストの、save:メソッドを使ってファイルに保存する。コンテキスには、永続ストアコーディネータが関連づけられているので、それに設定してあるファイルに保存することになる。

    保存する形式は、XML、バイナリ、SQLから選択することができる。それぞれの特徴は、以下の通りである。

    • XML
      テキスト形式になる。エキストエディタなどで、開いて読むことができる。ファイルサイズは大きくなり、読み書きのスピードも速くはない。
    • バイナリ
      バイナリ形式で書き出す。スピードはXMLより速くなる。
    • SQL
      SQLiteデータベースを利用する。スピードは最速になる。

    SQLの利用は、特に大規模なデータを取り扱うときに有利になるだろう。

    新着記事

    特設サイトの情報

      人気記事

      一覧

        イチオシ記事

        新着記事

        特別企画

        マイナビニュースマガジン