ページ

2008年2月25日月曜日

NSRect を CoreDataで扱う

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

以前、NSRect などが CoreDataで扱えたら便利と書いたが、NSValue というラッパークラスがあることに気がついた。これが使えないだろうか。

NSValue Class Reference

NSValue の生成メソッド:

– initWithBytes:objCType: 
+ valueWithBytes:objCType:
+ value:withObjCType:
+ valueWithNonretainedObject:
+ valueWithPointer:
+ valueWithPoint:
+ valueWithRange:
+ valueWithRect:
+ valueWithSize:


NSRect以外に NSPointや NSRange などよく使う構造体をオブジェクトとして扱うことができるようになる。


CoreDataのエンティティ属性のデータ型を「変換可能」(Transformable)にすれば、NSRectもCoreDataへ格納できるのでは?

参考:Non-Standard Persistent Attributes

さっそくやってみた。



エンティティのコードを生成させて型を NSValue に書き換えた。

@interface SampleEntity :  NSManagedObject 
{
}

@property (retain) NSValue* frame;    // frameにはNSRectが入る

@end



この値を保存するコードを実行してみる。


エラーが出た。。
*** -[NSKeyedArchiver encodeValueOfObjCType:at:]: this archiver cannot encode structs


NSKeyedArchiverでは構造体をエンコードできないとのこと。

Transformable Attributes によれば「変換可能」の場合の NSValueTransformer はデフォルトで NSKeyedUnarchiveFromDataTransformerName タイプが使われる。この場合、NSKeyedArchiverによってエンコードされたデータがファイルへ書き込まれることになる。このエンコード過程でエラーが発生したようだ。


Googleで探してみると同様の問題を取り上げたページがいくつかあった。

Re: coding struct with keyed archivers

Re: NSKeyedArchiver and NSValue

CocoaDev: EncodingNSRectAndNSPointInAKeyedArchiver

Archiver une NSValue avec NSKeyedArchiver
NSKeyedArchiverにカテゴリでCデータをアーカイブ/アンアーカイブするメソッドを実装する例が載っていた。


- - - -
簡単にはできそうもないな。