ページ

2008年2月27日水曜日

NSRect を CoreDataで扱う(その3)

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

さて今度は 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