今回は、UserDefaultsを用いて端末内に自作したクラスのデータを保存する方法を説明します。
とは言っても、最後まで説明すると長くなるので説明の前に完成したものを載せます。
class Animal: NSObject, NSCoding { private var id : Int! private var name : String! init(id: Int, name: String) { self.id = id self.name = name } //エンコード関数 forKeyは任意の文字列 func encode(with coder: NSCoder) { coder.encode(id, forKey: "id") coder.encode(name, forKey: "name") } //デコード関数 forKeyは任意の文字列 required init?(coder aDecoder: NSCoder) { id = aDecoder.decodeObject(forKey: "id") as? Int name = aDecoder.decodeObject(forKey: "name") as? String } //自作クラス->Data型へ変換 private static func archiveDataArray(indexDataArray: [Animal]) -> Data { do { // iOS11以降 if #available(iOS 11.0, *) { let data = try NSKeyedArchiver.archivedData(withRootObject: indexDataArray, requiringSecureCoding: false) return data // iOS11以前 } else { let data = NSKeyedArchiver.archivedData(withRootObject: indexDataArray) return data } } catch { fatalError("エンコード失敗") } } //UserDefaultsへデータを保存 public func saveDataArray(indexDataArray: [Animal]) { UserDefaults.standard.set(Animal.archiveDataArray(indexDataArray: indexDataArray), forKey: "") } //UserDefaultsからデータ取得 public func getData() -> [Animal] { var dataArray = [Animal]() let storedData = UserDefaults.standard.data(forKey: "") if storedData != nil { // iOS11以降 if #available(iOS 11.0, *) { if let storedData = UserDefaults.standard.object(forKey: "") as? Data { guard let unarchivedObject = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(storedData) as? [Animal] else { return [Animal]() } dataArray = unarchivedObject! } // iOS11以前 } else { if let storedData = UserDefaults.standard.object(forKey: "") as? Data { guard let unarchivedObject = NSKeyedUnarchiver.unarchiveObject(with: storedData) as? [Animal] else { return [Animal]() } dataArray = unarchivedObject } } } return dataArray } }
では説明に移ります。
まず始めに。。。
下のような自作クラスを作ったとします。
(クラスに拘りはないので、下記クラスの説明は省きます。。。)
class Animal { private var id : Int! private var name : String! init(id: Int. name: String) { self.id = id self.name = name } }
このクラスを次にNSObjectとNSCodingのクラスを継承させます。
(*あくまでも、ここでは説明の便宜上、上記クラスを自作クラスに継承させますが、実際に設計の事を考慮するとまた別のクラスを作成するのも手です。)
class Animal: NSObject, NSCoding { private var id : Int! private var name : String! init(id: Int, name: String) { self.id = id self.name = name } func encode(with coder: NSCoder) { coder.encode(id, forKey: "id") coder.encode(name, forKey: "name") } required init?(coder aDecoder: NSCoder) { id = aDecoder.decodeObject(forKey: "id") as? Int name = aDecoder.decodeObject(forKey: "name") as? String } }
次にそれぞれ「自作クラス->Data型変換」のための関数を作成します。
//自作クラス->Data型へ変換 private static func archiveDataArray(indexDataArray: [Animal]) -> Data { do { // iOS11以降 if #available(iOS 11.0, *) { let data = try NSKeyedArchiver.archivedData(withRootObject: indexDataArray, requiringSecureCoding: false) return data // iOS11以前 } else { let data = NSKeyedArchiver.archivedData(withRootObject: indexDataArray) return data } } catch { fatalError("エンコード失敗") } }
最後にUserDefaultsへ保存するための関数、UserDefaultsからデータを取得するための関数を作成して終わりです。
class Animal: NSObject, NSCoding { : : //UserDefaultsへデータを保存 public func saveDataArray(indexDataArray: [Animal]) { UserDefaults.standard.set(Animal.archiveDataArray(indexDataArray: indexDataArray), forKey: "") } //UserDefaultsからデータ取得 public func getData() -> [Animal] { var dataArray = [Animal]() let storedData = UserDefaults.standard.data(forKey: "") if storedData != nil { // iOS11以降 if #available(iOS 11.0, *) { if let storedData = UserDefaults.standard.object(forKey: "") as? Data { guard let unarchivedObject = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(storedData) as? [Animal] else { return [Animal]() } dataArray = unarchivedObject! } // iOS11以前 } else { if let storedData = UserDefaults.standard.object(forKey: "") as? Data { guard let unarchivedObject = NSKeyedUnarchiver.unarchiveObject(with: storedData) as? [Animal] else { return [Animal]() } dataArray = unarchivedObject } } } return dataArray } : : }
サーバーと接続をする必要がないアプリを作成する場合、
UserDefaultsを利用し、ユーザーのデータを端末上に保存しなければならない状況も多いと思います。
結構自分自身も利用する場面が多かったので、
良かったら参考にしてみて下さい。