以前、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データをアーカイブ/アンアーカイブするメソッドを実装する例が載っていた。
- - - -
簡単にはできそうもないな。