NSUserDefaultsに格納できるオブジェクトタイプは限定的
自分自身知らなかったのですが、NSUserDefaults
には setObject:forKey:
なんてメソッドがあります。setObject:
なんて言ってるのでテッキリ、どんなオブジェクトでも指定できるのかなと思ったのですが、案外そうでもなく、結局は plist に格納できるオブジェクトタイプに限定されている模様。
で、ドキュメントを見ても実際そのように書いてあるのですね...。
The value parameter can be only property list objects: NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary.
そしてまた、NSArray
やNSDictionary
のようなコレクションクラスの場合、そのコレクション内に入れるものも上記のオブジェクトタイプに限られます。
オブジェクトを何とかシリアライズして保存する
例えばUIColor
を保存したい場合はどうしましょうか。
考えてみれば、UIColor
を何らかの方法でシリアライズすれば良いのだと思います。UIColor
の場合は簡単で、色を扱うクラスですので R, G, B, Aの 4 要素を使ってシリアライズしても良いかと。
下記の例ですと、red, green, blue, alphaの要素をNSDictionary
形態に変換しています。
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
UIColor *color = [UIColor redColor];
//格納
CGFloat r, g, b, a;
[color getRed:&r green:&g blue:&b alpha:&a]; //RGBA要素を取り出す
[userDefaults setObject:@{@"red":@(r), @"green":@(g), @"blue":@(b), @"alpha":@(a)} forKey:@"color"];
//取出し
NSDictionary *dic = [userDefaults objectForKey:@"color"];
r = ((NSNumber *)dic[@"red"]).doubleValue;
g = ((NSNumber *)dic[@"green"]).doubleValue;
b = ((NSNumber *)dic[@"blue"]).doubleValue;
a = ((NSNumber *)dic[@"alpha"]).doubleValue;
UIColor *color_new = [UIColor colorWithRed:r green:g blue:b alpha:a];
NSKeyedArchiver
を使う
なにやら色々書きましたが...。NSCoding
に準拠したクラスであれば、NSKeyedArchiver
を使ってしまうのも手です。
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
UIColor *color = [UIColor redColor];
//格納
[userDefaults setObject:[NSKeyedArchiver archivedDataWithRootObject:color] forKey:@"color"];
//取出し
UIColor *color_new = [NSKeyedUnarchiver unarchiveObjectWithData:[userDefaults objectForKey:@"color"]];
ちなみに些細なことですが、 plist にNSData
を格納するとバイナリに base64 的なエンコードが掛かって文字列で格納されるようなので、少しファイルサイズが大きくなります。(plistがテキスト形態の場合)
保持するデータが単純なクラスの場合、できるだけNSDictionary
形態の方が良いかも知れません。が、面倒さを考えたらやっぱりNSData
ですかね...、些細な問題ですし。