2013/05/17更新

[XCODE] NSUserDefaultsへ自分で作成したクラスのインスタンスを保存する方法

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

こんにちは、@yoheiMuneです。
本日はiOSアプリ開発ネタで、NSUserDefaultsへカスタムクラスのオブジェクトを保存する方法をブログに書きたいと思います。

画像


データの永続化に便利なNSUserDefaults

みなさん、NSUserDefaultsという機能を使ってますかーーー?
NSUserDefaultsはデータを簡単に永続化できる機能で、テーブル定義とかDBコネクション作成とか面倒な手続きは一切無く、 便利にデータを永続化できる機能です。リファレンスは、こちらです。

NSUserDefaultsでは、Key-valueベースのデータ保存機能で、以下のように使うことが出来ます。
// データの保存
[[NSUserDefaults standardUserDefaults] setValue:@"もじ文字" forKey:@"key"];

// データの取得
NSString *moji = [[NSUserDefaults standardUserDefaults] objectForKey:@"key"];
これだけでデータを永続化できるのでとっても便利です。
ユーザーの設定値など簡単な情報はNSUserDefaultsに保存するようにして、コーディングを積極的にさぼれますw。

しかし、NSUserDefaultsに格納できる型は以下に制限されています。
NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary
Cocoaで使う基本的なデータ構造は格納できるのですが、自身で定義したクラス(例えばUserというクラスで名前と年齢を保持する)はNSUserDefaultsにはそのままでは格納することが出来ます。
このブログでは、自身で定義したクラスをNSUserDefaultsへ保存したり取得したりする方法を書きたいと思います。



カスタムオブジェクトをNSUserDefaultsへ保存/取得する方法

カスタムオブジェクトをNSUserDefaultsへ保存/取得するには、以下のステップを踏む必要があります。
  1. カスタムオブジェクトをNSDataへ変換する
  2. NSDataをNSUserDefaultsへ保存する
  3. NSUserDefaultsからNSDataを取得する
  4. NSDataからカスタムオブジェクトを復元する
NSDataとはバイナリーデータを表現するクラスですが、そのNSDataを利用してNSUserDefaultsへ格納することで、 カスタムオブジェクトをNSUserDefaultsへ保存することが可能となります。 以下ではそれぞれの手順を順に書いて行きます!



1、カスタムオブジェクトをNSDataへ変換する

カスタムオブジェクトをNSDataへ正しく変換するために、NSCodingプロトコルを利用します。 NSCodingプロトコルに定義されたメソッドを実装することで、カスタムオブジェクトの保持する値も含め、NSDataへ変換できます。

今回NSDataへ変換するクラスは、以下のCustomObjectクラスとします。
// インターフェース定義
@interface CustomObject : NSObject {
    int age;
    NSString *name;
}
@property int age;
@property(nonatomic, retain) NSString *name;
@end

// 実装定義
@implementation CustomObject
@synthesize age;
@synthesize name;
@end

まずは、NSCodingプロトコルを実装することを宣言します。
@interface CustomObject : NSObject <NSCoding> {
/*以下略*/
続いて、実装クラスで、NSDataへ変換するためのメソッドを実装します。
@implementation CustomObject
// シリアライズ時に呼ばれる
- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeObject:[NSNumber numberWithInt:age] forKey:@"age"];
    [coder encodeObject:name forKey:@"name"];
}
@end
引数で渡されるcoderというオブジェクトを使って、CustomObjectクラスのプロパティのエンコード指定を行います。 これで、CustomObjectクラスをNSDataへ変換することが出来るようになりました。

それではさっそくCustomeObjectクラスのインスタンスを、NSDataへ変換します。
// オブジェクトを作る
CustomObject *object = [[CustomObject alloc] init];
object.age = 20;
object.name = @"yoheiM";

// NSDataへ変換する
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:object];
NSDataへ変換する場合には、NSKeyedArchiverクラスのメソッドを使うと簡単に変換することが出来ます。
これでカスタムオブジェクトをNSDataへ変換できました。



2、NSDataをNSUserDefaultsへ保存する

これは簡単で、たった1行です。
[[NSUserDefaults standardUserDefaults] setValue:data forKey:@"key"];



3、NSUserDefaultsからNSDataを取得する

これも簡単です!
NSData *data2 = [[NSUserDefaults standardUserDefaults] objectForKey:@"key"];



4、NSDataからカスタムオブジェクトを復元する

NSDataからCustomObjectクラスのインスタンスを復元するためには、NSCodingプロトコルのメソッドをもう1つ実装する必要があります。
// デシリアライズ時に呼ばれる
- (id)initWithCoder:(NSCoder *)coder {
    self = [self init];
    if (self) {
        age = [[coder decodeObjectForKey:@"age"] intValue];
        name = [coder decodeObjectForKey:@"name"];
    }
    return self;
}
CustomObjectクラスのオブジェクトのインスタンス生成の時に呼ばれ、引数のcoderから値を復元する処理を記述します。

上記が実装できた状態で以下のように、NSDataからCustomObjectを復元することが出来ます。
CustomObject *object2 = [NSKeyedUnarchiver unarchiveObjectWithData:data2];
アンアーカイブするためには、NSKeyedUnarchiverクラスのメソッドを使うと便利です。
これでCustomObjectクラスのインスタンスを復元することが出来ました。



最後に

NSUserDefaultsへはNSDictionaryを格納できるので、構造化されたデータも格納できるのですが、やっぱりカスタムオブジェクトも格納したい。 そんな思いのもと、色々と調べて実装した結果をブログに残しました。
NSDictonaryでデータを保持すると値へアクセスするためにKey値を文字列で指定する必要があり、なかなか大変なので。

最後までご覧頂きましてありがとうございました!





こんな記事もいかがですか?

RSS画像

もしご興味をお持ち頂けましたら、ぜひRSSへの登録をお願い致します。