Study CoreData 2 ~時をさかのぼる 後編~

(前編からの続き)
 
そろそろ擬人化が困難になってきました…ので、正気に戻ります(笑)

注意:投稿者自身もCoraDataについて勉強中のため、このシリーズには誤りが含まれている可能性があります。もし、間違いに気付かれた方はコメント欄もしくはtwitterなどでご指摘いただけると幸いです<(_ _)>
また、開発環境はXcode3.2.3 iPhone SDK 4です。実機でのテストなどは自己責任でお願いいたします。

 
 

 
NSFetchedResultsControllerが出てきたところで、
検索条件やソート条件がセットされた<フェッチリクエスト>
<managedObjectContext>などを引数として渡して
<NSFetchedResultsController>をインスタンス化します。
 
(ここでは[sectionNameKeyPath:]の引数がnilになっていますが、ここにkeyPathを渡す事でUITableViewのセクションに対応するデータオブジェクトを設定できます)

そしてデリゲートを設定し、<fetchedResultsControllerプロパティ>に代入します。

NSFetchedResultsController *aFetchedResultsController =
 [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
         managedObjectContext:self.managedObjectContext
         sectionNameKeyPath:nil cacheName:@"Root"];

    aFetchedResultsController.delegate = self;

self.fetchedResultsController = aFetchedResultsController;

これで、<fetchedResultsController>を返す準備が整いました。

そして、不要になったインスタンスを解放して後片付けします。
 
 

NSError *error = nil;
if (![fetchedResultsController_ performFetch:&amp;error]) {

    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}

そして、このアクセサメソッドの最後の部分もかなり重要です!
[performFetch:]はBOOL値を返すメソッドになっています。

このメソッドのAbstractを見てみると…

オブジェクトを取得するためにフェッチリクエストを実行します。 処理が成功すればYES、失敗した場合にはNO(そしてエラー)を返します。 
フェッチリクエストが指定した<sectionNameKeyPath>がSortDescripterに含まれていない場合はエラーを返します。
このメソッドを実行した後でオブジェクトは<FetchedObjectプロパティ>にアクセスできるようになります。

(※相変わらずYahoo!翻訳からの意訳です。だいたいこんな内容かと)

つまり逆を返すと、

この処理をしておかないと結果的に
<FetchedObjectプロパティ>にアクセスできない
 = <fetchedResultsController>が使えない

って事のようですね。

 
最後にインスタンスを返して終了します。

return fetchedResultsController_;

 
 
7. アクセサメソッド
([-(NSFetchedResultsController *)fetchedResultsController])の
まとめ

ここまで呼んでくださった方本当にお疲れさまです!
 
このメソッドは、かなり細かく紹介したつもりです。
それには理由があるのですが、それは
今後アプリ独自のデータを扱っていくにあたって
変更/追加するべき処理が含まれているから

です。

つまり、どのようなデータを作り取り出すのかを決めるのに必要な内容になっているという事。

これはしっかりと理解しておいた方が良さそうですね。
 
 
…と、ここで終了です!
 
 
とはいきません!! (^〜^;)

このアクセサメソッドを読み解く中でさらっと流してしまったところがあります。
これです↓

NSEntityDescription *entity = 
[NSEntityDescription entityForName:@"Event" 
     inManagedObjectContext:self.managedObjectContext];

 
前述した内容では、

『<self.managedObjectContext>が持っている@”Event”ってブランドのものを…』ということをフェッチリクエストに教える。

と書きましたが、<managedObjectContextプロパティ>には触れませんでしたので、今度はコイツを探ってみます。
 
 
8. NSManagedObjectContextを探る

例によって⌘+ダブルクリックすると、下のようにズラッと検索結果が表示されます。
 

 
今はRootViewController.mで調べているので、
[M]-[RootViewController managedObjectContext]を見てみたいのですが、
実は、この<managedObjectContextプロパティ>のアクセサメソッドは@sythesizeによって自動生成されているだけなので、実装部のコードはありません。

…と言う事は、
RootViewController以外の場所でこのプロパティへの代入が行われているはず!
ってことで、残るはTodoCoreAppDelegateしかありませんね。

 
そういえば…どこかでお会いしませんでしたっけ……?
 
 
9. AppDelegate.mでの処理へ突入!!

そうです!
InterfaceBuilderとのお別れをし、身辺整理をしていた時にお会いしてました!
 

 
ここで

rootViewController.managedObjectContext = self.managedObjectContext;

という記述があります。

つまり、
rootViewControllerの<managedObjectContext>は、
このAppDelegate内で取得または生成

されているようです。
 
 
10. またまたさかのぼるのぼかさたまたま

そしてまた、例によって時間軸をさかのぼります。
 
 
下が、NSManagedObjectContextプロパティの実装部です。

簡単に説明すると<NSManagedObjectContext>とは、
データの状態/変更などをすべて記憶しているもののようです。

<CoreGraphics>のCGContextRefが、
インターフェイス上に描画した線や塗りの状態や、描画される前の状態を記憶
できるように、
<NSManagedObjectContext>はデータの状態を記憶できるもの
と考えてよいのではないでしょうか。

ここでは、
<NSPersistentStoreCoodinater>が<NSManagedObjectContext>にセット
されています。
なので、またさかのぼります。
 
 
次が<NSPersistentStoreCoordinatorプロパティ>の実装部になります。

ここでは、TodoCore.sqliteというファイルへのパス(ディレクトリ)をstoreURLとして取得。
[self managedObjectModel]を引数として渡した
<NSPersistentStoreCoordinator>のインスタンスを作成

そして、先程取得したディレクトリに
<NSSQLiteStoreType>のPersistentStoreを追加し、
更新されたPersistentStoreを返す
との事のようです。

if (![persistentStoreCoordinator_ 
  addPersistentStoreWithType:NSSQLiteStoreType
       configuration:nil URL:storeURL options:nil
          error:&amp;error]) {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
}

そして、それが失敗した時にはエラーが発生する。
 
 
<NSPersistentStoreCoordinator>は
永続的ストアコーディネータと訳されていますが、分かりにくいので
『持続性のあるデータ装置を管理するもの』
(ハードディスク/メモリに記憶するための管理をする)くらいに考えておいて良いのではないかと。
 
 
そして[self managedObjectModel]を辿ります。

ここで何をしているかと言うと
メインバンドルからTodoCore.momdというファイルへのパスを取得し、
それを元に<NSManagedObjectModel>のインスタンスを作成しています。

この<NSManagedObjectModel>というのが
“Study CoreData 2″の始めの方にに出てきた<NSManagedObject>と混同してしまいそうですが、
<NSManagedObject>がデータそのものというのに対して、<NSManagedObjectModel>はそのデータのための設計図
というところでしょうか。
 
 
そして、次回は
この<NSManagedObjectModel>(設計図)がどのように作られているのか
を見ていこうと思います。
 
 
…やっと原点までさかのぼれましたねぇε=( ̄。 ̄;)
いやぁ、長い旅路でした。

それでは、今回の最後にここまでで出てきたクラス(プロパティ)を簡単にまとめてみましょう。
 
 
11. まとめ
 
CoreDataを使ってUITableViewに表示するデータを取得するには…

・ <NSManagedObject>(データそのもの)からキー値コーディングを使って取り出す。

・<NSManagedObject>は<NSFetchedResultsController>からindexPathを使って取り出す。

・<NSFetchedResultsController>からオブジェクトを取り出すには、
     [(NSFetchedResultsControllerのインスタンス) performFetch:&error];を実行する必要がある。

・<NSFetchedResultsController>にはCoreDataのデータをUITableViewに効率的に表示するための機能が備わっている。

・<NSFetchedResultsController>には<NSFetchRequest>(データを取り出す条件など)を指定する必要がある。

・<NSFetchRequest>には、<NSManagedObjectContext>(データの状態を記憶している場所)にある<NSEntityDescription>(データの種類)や
取り出す際の<NSSortDescriptor>(ソート順)が必要で、UITableViewのsectionに対応するKeyなども指定できる。

・<NSManagedObjectContext>はAppDelegateから渡されている。

・<NSManagedObjectContext>を生成する際には…
     まず、<NSManagedObjectModel>(データの設計図)を取得する。
     それを利用して、SQLiteデータベースと<NSPersistentStoreCoordinator>(ハードディスクに記憶するための管理をする)が生成される。
     その<NSPersistentStoreCoordinator>が<NSManagedObjectContext>にセットされている。

と、今のところは何となくこれくらいは分かりました。

そして、この次はいよいよCoreData’s Core(核)にせまっていきます!!

お楽しみに〜
 
 
 
まぁ、僕自身勉強しながらのエントリーですので、
説明不足な箇所や誤りは多々あると思いますが、気付いた方は教えて頂けるとウレシいです<(_ _)>

それでは、しーゆーとぅもろぉ〜♬

広告

Study CoreData 2 ~時をさかのぼる 後編~」への1件のフィードバック

  1. ピンバック: [朝刊] 池上彰さんの人気が高騰しています。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中