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は起動時?に一旦全部保存したものをメモリに展開するっぽいので、
あまり保存しすぎにも注意。
他にもいい方法あったら教えてください