独自のオブジェクトをシリアライズできるようにする。
久しぶりに扱ってはまった。調べ直したのでメモっておく。
例えば、NSUserDefaultやSQLiteを使ってデータを保存したいとき、独自に作成したオブジェクトだとそのままでは保存できない。
それらのデータストアはNSStringやNSArray、NSDataなど特定のオブジェクト以外はデータを保持しておいてくれないので、そういう時には独自オブジェクトにNSCodingインターフェースを実装して、アーカイバを使ってNSDataにシリアライズしてから保存するようにする。
保存対象のオブジェクト:
@interface MyObject : NSObject<NSCoding> { NSString *aString; NSString *bString; } @end @implementation MyObject // ... // encodeWithCoderとinitWithCoderを実装 - (void) encodeWithCoder:(NSCoder *)coder { // シリアライズ時に呼び出される。 [coder encodeObject:aString forKey:@"aString"]; [coder encodeObject:bString forKey:@"bString"]; } - (id) initWithCoder:(NSCoder *)coder { // デシリアライズ時に呼び出されるイニシャライザ if (self = [super init]) { // オブジェクトの生成ではないので、retainを忘れないように。 aString = [[coder decodeObjectForKey:@"aString"] retain]; bString = [[coder decodeObjectForKey:@"bString"] retain]; } return self; } // ... @end
こんな感じで実装しておく。
それで、使い方は以下の通り。例えばNSUserDefaultsを使う場合。
// 配列の中にぶち込んであっても大丈夫。 NSArray *array = [NSArray arrayWithObjects: [[MyObject allow] init], @"hogehoge", nil ]; // NSKeyedArchierでシリアライズ NSData* data = [NSKeyedArchiver archivedDataWithRootObject:array]; [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"array"]; // NSKeyedUnarchiverで、デシリアライズ NSData *deData = [[NSUserDefaults standardUserDefaults] objectForKey:@"array"]; NSArray *deArray = [NSKeyedUnarchiver unarchiveObjectWithData:]; for (id myObj in deArray) { NSLog(@"%@", [myObj className]); // MyObject, NSStringと出る。 }