前回紹介したサイトに掲載されていたNSKeyedArchiver にカテゴリを追加する方法を試してみる。
まず CoreDataへ行く前に NSKeyedArchiver/NSKeyedUnarchiver を実装した簡単なサンプルで試してみる。
ソースコード:ArchiveSample.zip
"Archive" ボタンを押すと NSRect {{10, 20} , {100, 200}}がデスクトップ上に archiver.sampleというファイル名で保存される。
"UnArchive" ボタンを押すと archiver.sampleを読み込み、NSRectに戻して画面に表示する。
MyController.m
-(id)init
{
if (self = [super init]) {
rect = [[NSValue valueWithRect:NSMakeRect(10, 20, 100, 200)] retain];
rect_string1 = NSStringFromRect([rect rectValue]);
rect_string2 = @"";
}
return self;
}
インスタンス変数 rect がArchiver対象のNSRect。rect_string1, 2 は画面表示用の文字列でラベルから bindingされている(文字列を変更すると画面に反映される)。
- (IBAction)archive:(id)sender
{
BOOL result = [NSKeyedArchiver archiveRootObject:rect toFile:[self filename]];
}
Archiverボタンが押されたら NSKeyedArchiver#archiveRootObject:toFile: で rectを指定し保存を行う。通常では NSKeyedArchiverは構造体をサポートしていないので下記のエラーが出る。
*** -[NSKeyedArchiver encodeValueOfObjCType:at:]: this archiver cannot encode structs
そこで サイトに紹介されていたコードを拝借してカテゴリで Cの構造体をサポートするコードを追加する。
@interface NSKeyedArchiver (MyKeyedArchiver)
- (void)encodeValueOfObjCType:(const char *)valueType at:(const void *)address;
@end
@implementation NSKeyedArchiver (MyKeyedArchiver)
- (void)encodeValueOfObjCType:(const char *)valueType at:(const void *)address
{
NSMutableData *datas = [NSMutableData data];
NSArchiver *arch = [[NSArchiver alloc] initForWritingWithMutableData:datas];
[arch encodeValueOfObjCType:valueType
at:address];
[self encodeObject:[NSData dataWithData:datas]];
[arch release];
}
@end
するとエラーが出なくなる。
UnKeyedArchiverも同様にカテゴリを追加する。
- - - -
さて次回は CoreData で使ってみる。