[iOS][Mac] CoreData - マイグレーション[2] 自動マイグレーションで FUNCTIONを使う

2010年12月7日火曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

前回 NSEntityMigrationPolicy を使ったマイグレーションを紹介した。

[前回] Cocoaの日々: [iOS][Mac] CoreData - マイグレーション[1] NSEntityMigrationPolicy を使う

NSEntityMigrationPolicy を使うことで複雑なマイグレーションを行うことができる。前回は NSDate から月と日を抽出するコードを書いたが、これぐらいであれば自動マイグレーション(Lightweigt Migration)が使えないだろうか。ドキュメントを読み返していると FUNCTION が使えそうなのがわかったのでこれを試してみる。


サンプル


まずは結果から。前回のコードを書き換えて自動マイグレーションに切り替えた。マッピングモデルはこんな感じ。
前回と同じ。後で説明するが NSEntityMigrationPolicy を今回も使う。
day と month の値式に今回は FUNCTION を記述。
FUNCTION($entityPolicy, "monthOfDate:" , $source.timeStamp)
ドキュメントを見つけられなったので推測になるが FUNCTION は最初の引数にメッセージを投げる先のインスタンス、2番目にセレクタ(文字列)、3番目以降がセレクタの引数、といった仕様のようだ。指定したインスタンスへ指定した引数でメッセージを投げ、その結果が移行先の属性値として使われる。

$entityPolicy は「カスタムポリシー」で指定したクラスのインスタンスを指す。今回は NSEntityMigrationPolicy のサブクラス EventEntityMigrationPolicy を指定した。この $ で始まる予約語には次のものがある。
NSMigrationManagerKey: $manager
NSMigrationSourceObjectKey: $source
NSMigrationDestinationObjectKey: $destination
NSMigrationEntityMappingKey: $entityMapping
NSMigrationPropertyMappingKey: $propertyMapping
NSMigrationEntityPolicyKey: $entityPolicy
Core Data Model Versioning and Data Migration Programming Guide: Mapping Overview より転載)

EventEntityMigrationPolicy の実装はこう。
@implementation EventEntityMigrationPolicy

- (NSNumber*)monthOfDate:(NSDate*)date
{
 NSCalendar* calendar = [[[NSCalendar alloc]
    initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
 NSDateComponents* components = [calendar components:NSMonthCalendarUnit|
    NSDayCalendarUnit fromDate:date];
 return [NSNumber numberWithInteger:[components month]];
}
- (NSNumber*)dayOfDate:(NSDate*)date
{ 
 NSCalendar* calendar = [[[NSCalendar alloc]
    initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
 NSDateComponents* components = [calendar components:NSMonthCalendarUnit|
    NSDayCalendarUnit fromDate:date];
 return [NSNumber numberWithInteger:[components day]];
}

前回の create..メソッドはコメントアウトしてある。


備考


FUNCTION のターゲットオブジェクト


Event という名前の NSManagedObjectContext をサブクラスを用意して、そこに -dayOfDate: -monthOfDate: を実装したが、実行時にはエラーとなった。
e[8858:207] -[NSManagedObject monthOfDate:]: unrecognized selector sent to instance 0x4d87c10
[8858:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException',
 reason: '-[NSManagedObject monthOfDate:]: unrecognized selector sent to instance 0x4d87c10'

モデル定義でクラス指定しても駄目だった。
本来はここにマイグレーションコードが書けるといいのだが(NSEntityMigrationPolicyのインスタンスを用意する必要がなくなる)。


属性マッピングの値式に文字列を指定

属性マッピングの値式に文字列を書くときは ""で囲う。
◯ "Hello" × Hello ※ null扱いになる



ソースコード


GitHub からどうぞ。
xcatsan/iOS-Sample-Code at 2010-12-07 - GitHub

Responses

Leave a Response

人気の投稿(過去 30日間)