Xcode
iOS
Swift
UserDefaults
型安全

UserDefaultsを型安全に使用する方法(#functionを使用する方法とSwiftyUserDefaultsの紹介)

はじめに

アプリ内でデータを保存する方法にはKeyChainを使う方法とUserDefaultsを使う方法があります。
UserDefaultsは容易に設定値などを保存できることから多くのアプリで利用されていますが、以下のように普通に使うと型安全ではなく、キーを文字列定義しなければタイプミスを引き起こすなどの問題が発生します。

let value = "value string"
UserDefaults.standard.set(value, forKey: "key string")
let userDefaultsValue = UserDefaults.standard.string(forKey: "key string")
// "key string"を文字列定義する必要がある(文字列定義していないと取り出すときにtypoしてしまう危険性がある)
// stringで入れても、stringで出すということが"key string"と紐付いていないため、誤った型で取り出そうとすることもできてしまう
// 誤った例 : let userDefaultsValue = UserDefaults.standard.integer(forKey: "key str")

functionを使用する方法

UserDefaultsのextensionを用意し、functionを使うことでキーを文字列定義する必要がなく、型安全に使用することが可能になります。

extension UserDefaults {
    var isTutorialFinished: Bool {
        // 以下のように#functionと指定することで`isTutorialFinished`がキーの文字列として指定される
        get { return bool(forKey: #function) }
        set { set(newValue, forKey: #function) }
    }
}

この方法を使うことによるメリットとして、簡易に定義でき、しかも型安全であるということが挙げられますが、この他にももう一点、同じキー値が使用される危険性が低くなるというメリットもあります。
getとsetを記述しなければならないという観点から言えば少し冗長ではあるものの、規模がそこまで大きくないアプリや、OSSの導入が難しい場合などには有効な手段だと考えられます。
もしも規模が少し大きくなって、#functionなどと書くのが面倒であれば、以下のようなfunctionを作るとより良いでしょう。

private func getBool(key: String = #function) -> Bool {
    return UserDefaults.standard.bool(forKey: key)
}

private func setBool(_ newValue: Bool, key: String = #function) {
    UserDefaults.standard.set(newValue, forKey: key)
}

var isTutorialFinished: Bool {
    get { return getBool() }
    set { setBool(newValue) }
}

SwiftyUserDefaults

UserDefaultsを簡単に使う為の有名なライブラリとしてSwiftyUserDefaultsというライブラリがあります。OSSの導入に問題がない場合はこちらのライブラリを使用するのもいいでしょう。
使用方法はいたって簡単で、以下のようにDefaultsKeysを定義していくと、すぐさまget/setができるようになります。

// キーとなる文字列を定義
extension DefaultsKeys {
    static let username = DefaultsKey<String?>("username")
    static let launchCount = DefaultsKey<Int>("launchCount")
}
// 以下のように簡単にget/setができるようになります
// Get and set user defaults easily
let username = Defaults[.username]
Defaults[.hotkeyEnabled] = true

// Modify value types in place
Defaults[.launchCount] += 1
Defaults[.volume] -= 0.1
Defaults[.strings] += "… can easily be extended!"

// Use and modify typed arrays
Defaults[.libraries].append("SwiftyUserDefaults")
Defaults[.libraries][0] += " 2.0"

// Easily work with custom serialized types
Defaults[.color] = NSColor.white
Defaults[.color]?.whiteComponent // => 1.0

このライブラリを使用するメリットとしては、上記サンプルに記載しているように、+=や-=の演算が可能なことや、複数の異なる型の配列の保存が容易なことにあります。
UserDefaultsを使用する上では非常に使い勝手の良いライブラリなのでおすすめです。

参考URL