2013年1月23日水曜日

CoreData 小技 EntityからNSDictionaryをとる



CoreDataやってるとさ〜Mo(MamagedObject)とNSDictionaryのやりとりってめんどいですよね?
いちいち代入とかやってらんないよ!
っと言う方の為に小技を公開しちゃいます。


<NSDictinary to MO>


Entity * entity = ... ;
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:
    @"value",@"title",
    @"createDate",@"data",
     nil];
[entity setValuesForKeysWithDictionary:dic];

ま、これは厳密にいうとDate型とかFommaterで変換しなきゃいけないのでそんなに使わないですねw
よく使うのがMO to Dictionaryでしょう。

<MO to Dictionary>


Entity *entity = [[DataManager EntityListFrom:@"Entity" sort:nil pred:nil]lastObject];
NSDictionary *dic = [entity dictionaryWithValuesForKeys:[[[entity entity] attributesByName] allKeys]];


ちなみに前回のデータ取得の共通メソッドにて一行

[fetchRequest setResultType:NSDictionaryResultType];

と書けば最初からDictionaryでリストをとれます。

CoreData データ呼び出しの共通メソッド

前回のCreateに続いてReadの共通メソッド書きます。

ま、こんな感じ。
パラメータにエンティティの名前。そしてSortDescriptorとPredicateとlimitです。
SortDescriptorとPredicateについては他のところでも解説が多いので、そちらをみてください。
気が向いたら書くかもしれませんが。。。

DataManager.m
+(NSArray *)EntityListWithName:(NSString *)entityName  sort:(NSSortDescriptor *)sort
  pred:(NSPredicate *)pred  limit:(int)limit {

//※Moを拡張してます
NSManagedObjectContext* managedObjectContex=[NSManagedObjectContext managedObjectContextForCurrentThread];
    
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // 取得するエンティティを設定
    NSEntityDescription *entityDescription;
    entityDescription = [NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContex];
    [fetchRequest setEntity:entityDescription];
if(sort!=nil){
        NSArray *sortDescriptors;

        sortDescriptors = [[NSArray alloc] initWithObjects:sort, nil];
        [fetchRequest setSortDescriptors:sortDescriptors];
}else{
        NSArray *sortDescriptors;
        sortDescriptors = [[NSArray alloc] initWithObjects: nil];
        [fetchRequest setSortDescriptors:sortDescriptors];
    }
    
    // 取得条件の設定
if(pred!=nil)[fetchRequest setPredicate:pred];
    // 取得最大数の設定
    if(limit>0)[fetchRequest setFetchBatchSize:limit];
    // データ取得用コントローラを作成
    NSFetchedResultsController *resultsController;
 
    resultsController = [[NSFetchedResultsController alloc]
                          initWithFetchRequest:fetchRequest
                          managedObjectContext:managedObjectContex
                          sectionNameKeyPath:nil
                          cacheName:entityName];  
    // DBから値を取得する
NSError* error = nil;
    if (![resultsController performFetch:&error]) {
        abort();
    }
    NSArray *result = resultsController.fetchedObjects ;
    resultsController=nil;
    managedObjectContex=nil;
    
return result;
}


ちなみにカテゴリ実装でNSManagedObjectに下記を実装してます。
+ (NSManagedObjectContext *)managedObjectContextForCurrentThread {
    return [NSManagedObjectContext managedObjectContextForThread:[NSThread currentThread]];
}


呼び出しで共通メソッド作っておくと、さくっとArrayで返ってくるのでです(^^)

CoreData データ取得の共通メソッドを作っておく

こんにちは!ひさしぶりの投稿です。

今回はCoreDataについて。
基本的な部分エンティティの設定やら何やらは本でも読んでもらうとして。
それらを実装済みの状態で簡単にCoreDataを扱うサンプルを書いて行きたいと思います。

DBっていえばCRUD(クラッド)できないとですね。ちなみにCRUDとは

 C=Create
   R=Read
   U=Update
   D=Delete

です。
え?そんなこと知ってるって?
そーですね。失礼しましたw


とりあえずはRDBでいうSelect投げられないとですね。
でもCreateしないとReadできないか。

そんなわけでまずはCreateから。


とりあえずの仕掛けとして、シングルトンでmanagerクラス作るのが常識かもしれませんが、簡単にAppDelegateにてcoreDateの設定周りを書ききりmanagedObjectContextとかもAppDelegateに保持する感じで説明します。

AppDelegate.h

@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;

ただし、ほかのCoreData周りのコードも含めて別途シングルトンの管理クラスを作ります。
ここではDataManagerとでもしておきましょか。

DataManager.m


+(NSManagedObjectContext *)managedObjectContext{
     AppDelegate *delegate=(AppDelegate*)[UIApplication     sharedApplication].delegate;
return delegate.managedObjectContext;
}

続いて呼び出し側

簡単に言うと、インスタンス作ってそいつのプロパティに値入れて保存。
ちなみにUpdateの場合もインスタンスを呼び出して保存でいけちゃいますw

YourClass.m
Order *orderEntity = [NSEntityDescription insertNewObjectForEntityForName:@"Order" inManagedObjectContext:[DataManager managedObjectContext]];

    orderEntity.pos_order_id = order.orderId;
    orderEntity.amount = [NSNumber numberWithInt:order.orderAmount];
    orderEntity.created = order.orderDate;
    orderEntity.updated = order.orderDate;
    
        NSError *error = nil;
    [[DataManager managedObjectContext] save:&error];
    if (error) {
        //ここにエラー制御書きます
    }



はい、簡単ですね。
次回はReadについて書きたいと思います。