さて今度は CoreDataで NSRectを保存してみる。
ソースコード:sp5.zip
サンプルを実行すると新規ドキュメントが一つ作成される。「ADD」ボタンを押すと色の着いた四角が追加される。この四角が CoreDataのエンティティに対応する。
エンティティのヘッダ SampleEntity.h
@interface SampleEntity : NSManagedObject
{
}
@property (retain) NSColor* color;
@property (retain) NSValue* frame;
@property (retain) NSNumber* order;
@end
frameに今回の目的である NSRect を格納している(実際には NSValueでラップしている)。
プロジェクトはテンプレート "Core Data Document-based Application" を使い必要なクラス(NSPersistentDocumentのサブクラス)を自動生成している。これに四角を描画する MyView を追加してある。エンティティデータへのアクセスは NSArrayControllerを使って行う。各オブジェクト間の関連は次のとおり。
再描画の為に MyViewは Array Controller の managedObjectsを監視(Observing)している。
MyView.h
-(void)awakeFromNib
{
[_array_controller addObserver:self
forKeyPath:@"arrangedObjects"
options:NSKeyValueObservingOptionNew
context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
[self setNeedsDisplay:YES];
}
アウトレットで接続した Array Controller を通じて SampleEntityの配列を取り出し、ソートし、四角を描画する。
- (void)drawRect:(NSRect)rect {
NSArray *list = [_array_controller valueForKey:@"arrangedObjects"];
NSSortDescriptor* sort_desc = [[[NSSortDescriptor alloc] initWithKey:@"order" ascending:YES] autorelease];
for(SampleEntity *entity in [list sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort_desc]]) {
[entity.color set];
NSRectFill([entity.frame rectValue]);
}
}
これで表示までが整った。最後に前回同様 NSKeyedArchiver/NSKeyedUnarchiver にカテゴリを追加すれば NSRect(をラップした NSValue)を CoreDataで保存/読み込みができるようになる。
無事にファイルが作成できて、これを読み込むこともできる。
"DUMP"ボタンを押した場合は SampleEntityオブジェクトの配列をコンソールにデバッグ出力する。
なお読み込んだ CoreDataを NSArrayController に反映させるには属性の "Prepares Content" にチェックを入れて置く必要がある。
- - - -
カテゴリの追加で NSRectが CoreDataで扱えるようになった。ただしわざわざ NSKeyedArchiverから構造体サポートを取り除いた(あるいは付けなかった)理由があることから、これはやるべきでは無いかもしれない。正攻法としては ADCのドキュメントで紹介されているような2つの属性を用意する方法がある。
Non-Standard Persistent Attributes