2015年11月19日木曜日

NSUserDefaultsにenumを保存

変数currentStageは、下のように定義されてるenum(列挙型)の値が入ってる。
これをUserDefaultsに保存しようと思ったのだが、直接保存できないようなので調べたよ。

enum stage:String {
    case forest
    case beach
    case room
    case wheatField

}


まずそのまま保存するのはどうにもこうにも無理らしいので、扱いやすいrawValueを以下のように設定してやる。
ここではStringにしてる(使い方によってはIntでもいい)。
そのrawValueをString値(または数値)として保存するわけだ。

enum stage:String {
    case forest = "forest"
    case beach = "beach"
    case room = "room"
    case wheatField = "wheatField"

}

保存時
    func saveData() {
        let ud = NSUserDefaults.standardUserDefaults()
        ud.setObject(currentStage.rawValue, forKey: "currentStage")
    }


読み込んだら今度はそれをenum型に戻すんだけど、これがだいぶ悩んだ。
enum型にはメソッドがあって、rawValueを引数にしてやればいいのだな。
んで、引数の型をas! Stringとして強制的にStringに変換して。
さらにXcode様の指示どおり、最後にも!を付けたよ。
多分これでうまくいってる。

読み込み時
    func loadData() {
        let ud = NSUserDefaults.standardUserDefaults()
        //Stringで保存されたcurrentStageを列挙型stageの値に戻す
        currentStage = stage(rawValue: ud.objectForKey("currentStage") as! String)!
    }


もう21世紀なんだから、言語内で扱える型は全て直接読み書きできるようにすべきだと思うんだけど、どうだろうか?
いちいちこんなことで頭悩ますなんてアホらしいよね。


なお、UserDefaultsにあらかじめデータが入っていない状態で読み出そうとするとnilが返るため、きちんとチェックしておかないと最悪アプリが落ちることになる。
下記のようにif文のオプショナルバインディングというのを使うとコードが少し楽。
ud.objectForKey("currentStage")の結果がnilじゃなかったら値をtestに代入し、nilだった場合はtestにはfalseが入るためにelse文が実行されるというSwiftの仕組み。

        if let test = ud.objectForKey("currentStage") {
            //Stringで保存されたcurrentStageを列挙型stageの値に戻す
            currentStage = stage(rawValue: test as! String)!
            print("保存済み")
        } else {
            print("保存されてない")
        }

0 件のコメント:

コメントを投稿