【Swift】[30]自作クラスをUserDefaultsに保存する方法

今回は、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
        }
    }

このクラスを次にNSObjectNSCodingのクラスを継承させます。

(*あくまでも、ここでは説明の便宜上、上記クラスを自作クラスに継承させますが、実際に設計の事を考慮するとまた別のクラスを作成するのも手です。)

    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を利用し、ユーザーのデータを端末上に保存しなければならない状況も多いと思います。

結構自分自身も利用する場面が多かったので、

良かったら参考にしてみて下さい。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です