LoginSignup
2
1

More than 5 years have passed since last update.

Structの保存

Last updated at Posted at 2017-01-15

Structの保存をしたい

swiftのStructってデータの管理に便利ですよね。
私はよくJSONで受け取ったデータをStructにパースして使っています。

でもUserDefaultsにStructを保存することはできません。
なのでDictionaryを使ってなんとかして見るというお話しです。

例えば

このユーザーデータを保存したいとします。


struct SampleUserData {
    var id:Int
    var name:String
    var profileUrls:profileUrlData

    struct profileUrlData {
        var midium:String
        var original:String
        var small:String

        init(json: JSON){//JSONはSwiftyJSON 
            self.small = json["small"].stringValue
            self.original = json["original"].stringValue
            self.midium = json["midium"].stringValue
        }
    }

    init(json: JSON){
        self.name = json["name"].stringValue
        self.id = json["id"].intValue
        self.profileUrls = profileUrlData(json: json["profile_urls"])
    }
}

実装

まず保存可能な型が批准するプロトコルを作ります。


protocol Storable {//保存したい型が批准する
    var dict:[String:Any]{get}
    init(dict: [String:Any])
}

で保存したいStructを批准させます。


struct SampleUserData:Storable {
    var name:String
    var id:Int
    var profileUrls:profileUrlData

    var dict: [String : Any]{//保存用
        return ["name": name,"id": id,"profile_urls": profileUrls.dict]
    }

    struct profileUrlData:Storable {
        var midium:String
        var original:String
        var small:String

        var dict: [String : Any]{//保存用
            return ["midium":midium,"original": original,"small": small]
        }

        init(json: JSON){
            self.small = json["small"].stringValue
            self.original = json["original"].stringValue
            self.midium = json["midium"].stringValue
        }
        init(dict: [String : Any]) {//展開用Init
            self.midium = dict["midium"] as? String ?? ""
            self.original = dict["original"] as? String ?? ""
            self.small = dict["small"] as? String ?? ""
        }
    }

    init(json: JSON){
        self.name = json["name"].stringValue
        self.id = json["id"].intValue
        self.profileUrls = profileUrlData(json: json["profile_urls"])
    }
    init(dict: [String : Any]) {//展開用Init
        self.name = dict["name"] as? String ?? ""
        self.id = dict["id"] as? Int ?? 0
        self.profileUrls = profileUrlData(dict: (dict["profile_urls"] as? [String: Any] ?? [:]))
    }
}

最後にUserDefaultsをちょっといじります。


extension UserDefaults {
    func set(_ value: Storable,forKey defaultName: String){
        self.set(value.dict, forKey: defaultName)
    }
    func `struct`<T: Storable>(type: T.Type,forKey defaultName: String)->T?{
        return T(dict: dictionary(forKey: defaultName) ?? [:])
    }
}

使い方

let data:JSON //APIとかから取ってきたJSON
let defaults = UserDefaults()
let userData = SampleUserData(json: json)//保存するデータ

//保存する時
defaults.set(userData, forKey: "sampel_key")

//読み込む時
let loadUserData = defaults.struct(type: SampleUserData.self, forKey: "sampel_key")

これで保存できると思います。
ただしStructみたいな大きなものの保存は時間がかかることが多いと思うので、
Asyncスレッドで行なっとほうがいいと思います。

あとUserDefaultsは起動時?に一旦全部保存したものをメモリに展開するっぽいので、
あまり保存しすぎにも注意。

他にもいい方法あったら教えてください

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1