NSDictionaryから直接CoreDataへ保存したい



WebAPIで取得してきたデータは一旦NSDictionary型で取り扱うかと思います。
こいつをそのままCoreDataに保存できたら便利ですよね。


例として以下の様なフォーマットでAPIのレスポンスが返ってくる場合

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
	<dict>
		<key>notification</key>
		<dict>
			<key>created_at</key>
			<date>2013-03-19T09:22:07Z</date>
			<key>id</key>
			<integer>389</integer>
			<key>notifications_type</key>
			<string>typeA</string>
			<key>notifier_id</key>
			<integer>1</integer>
			<key>notifier_type</key>
			<string>User</string>
			<key>source_id</key>
			<integer>99</integer>
			<key>source_type</key>
			<string>Relationship</string>
			<key>text</key>
			<string>test message1</string>
			<key>updated_at</key>
			<date>2013-03-19T09:22:07Z</date>
			<key>user_id</key>
			<integer>11</integer>
		</dict>
	</dict>
	<dict>
		<key>notification</key>
		<dict>
			<key>created_at</key>
			<date>2013-03-14T07:27:13Z</date>
			<key>id</key>
			<integer>316</integer>
			<key>notifications_type</key>
			<string>typeB</string>
			<key>notifier_id</key>
			<integer>4</integer>
			<key>notifier_type</key>
			<string>User</string>
			<key>source_id</key>
			<integer>241</integer>
			<key>source_type</key>
			<string>Schedule</string>
			<key>text</key>
			<string>message 2</string>
			<key>updated_at</key>
			<date>2013-03-17T06:57:11Z</date>
			<key>user_id</key>
			<integer>11</integer>
		</dict>
	</dict>
</array>
</plist>

```

対応するモデルは以下のように設定します。
plistの型とプロパティ名を一致させるように登録します

```objectivec
@interface Notification : NSManagedObject

@property (nonatomic, retain) NSDate * created_at;
@property (nonatomic, retain) NSNumber * id;
@property (nonatomic, retain) NSString * text;
@property (nonatomic, retain) NSDate * updated_at;
@property (nonatomic, retain) NSNumber * user_id;
@property (nonatomic, retain) NSString * notifications_type;
@property (nonatomic, retain) NSNumber * notifier_id;
@property (nonatomic, retain) NSString * notifier_type;

@end
```

また、カテゴリ機能を使ってNSManagedObjectを機能拡張し
プロパティ名一覧を取得できるようにします

```objectivec
#pragma mark - NSManagedObject 拡張
@interface NSManagedObject (propertyNames)
+(NSArray*)propertyNames;
@end

@implementation NSManagedObject(propertyNames)

//プロパテイ名一覧の取得
+(NSArray*)propertyNames
{
    unsigned int cnt;
    objc_property_t *properties =  class_copyPropertyList([self class], &cnt);
    NSMutableArray* propNames = [NSMutableArray arrayWithCapacity:cnt];
    for (int i =0; i< cnt; i++) {
        objc_property_t property = properties[i];
        const char* propName = property_getName(property);
        NSString* propertyName = [NSString stringWithUTF8String:propName];
        [propNames addObject:propertyName];
    }
    
    free(properties);
    return propNames;
}


@end

```

ここまでお膳立てしますと以下のコードで代入処理ができるようになります。


```objectivec

//dictの中にAPIの取得した情報が格納されている

Notification* notification = [NSEntityDescription
                        insertNewObjectForEntityForName:@"Notification"
                        inManagedObjectContext:self.managedObjectContext];
        
[notification setValuesForKeysWithDictionary:[dict dictionaryWithValuesForKeys:[Notification propertyNames]]];


```

jsonがインターフェースとなる場合、plistと違って型情報が値と文字列しか無いため
さらなる工夫が必要になるかもしれません。