Pure-Swift library for safe access to UserDefaults
- Xcode 9
- Swift 4.0+
- iOS 10.0+
CocoaPods is a dependency manager for Cocoa projects.
To integrate SafeDefaultsKit into your Xcode project using CocoaPods, add the following line to your Podfile
and run pod install
.
pod 'SafeDefaultsKit', git: 'https://github.com/jrsaruo/SafeDefaultsKit.git'
Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.
To integrate SafeDefaultsKit into your Xcode project using Carthage, specify it in your Cartfile
:
github "jrsaruo/SafeDefaultsKit"
Run carthage update
to build the framework and drag the built SafeDefaultsKit.framework
into your Xcode project.
You can define original keys and safely access to UserDefaults
by using them.
// Initialize your Defaults
let defaults = YourDefaults()
// Set value for Defaults
defaults.set("saved string", forKey: .definedKey)
// Get value from Defaults
print(defaults.string(forKey: .definedKey) ?? "no value") // -> "saved string"
// Remove value from Defaults
defaults.removeObject(forKey: .definedKey)
print(defaults.string(forKey: .definedKey) ?? "no value") // -> "no value"
By dividing Defaults for each purposes, it becomes easier to manage keys.
let loginInfoDefaults = LoginInfoDefaults() // LoginInfoDefaults has "loginDate" key
loginInfoDefaults.set(Date(), forKey: .loginDate)
let settingDefaults = SettingDefaults() // SettingDefaults has "mainColor" key
settingDefaults.set("red", forKey: .mainColor)
At first, declare the type that conforms to the SafeDefaults
protocol. This requires nested Enum named Keys
that conforms to the DefaultsKey
protocol and stores string raw values, and its cases are used as keys for your Defaults.
struct SampleDefaults: SafeDefaults {
enum Keys: String, DefaultsKey {
case userName
}
}
SampleDefaults().set("Tom", forKey: .userName)
// same as: UserDefaults.standard.set("Tom", forKey: "userName")
DefaultsKey
requires the uniqueValue
property, used as the key name for UserDefaults
.
uniqueValue
's default value is its raw value.
struct SampleDefaults: SafeDefaults {
enum Keys: String, DefaultsKey {
case userName = "customizedKeyForUserName"
}
}
SampleDefaults().set("Tom", forKey: .userName)
// same as: UserDefaults.standard.set("Tom", forKey: "customizedKeyForUserName")
If you declare uniqueValue
explicitly, it is used as the key name instead of the raw value.
struct SampleDefaults: SafeDefaults {
enum Keys: String, DefaultsKey {
case userName
// customize the key name for UserDefaults
var uniqueValue: String {
return "SampleDefaults.\(Keys.self).\(self.rawValue)"
}
}
}
SampleDefaults().set("Tom", forKey: .userName)
// same as: UserDefaults.standard.set("Tom", forKey: "SampleDefaults.Keys.userName")
getter methods for double, float, integer return optional value. If the specified key doesn‘t exist, these methods return nil
.
UserDefaults.standard.removeObject(forKey: "removed")
UserDefaults.standard.integer(forKey: "removed") // -> 0
YourDefaults().integer(forKey: .removed) // -> nil
uniqueValue
is used as key name for UserDefaults
and default is its raw value, so there is fear that some keys conflict each other.
struct BookDefaults: SafeDefaults {
enum Keys: String, DefaultsKey {
case id
}
}
struct ComicDefaults: SafeDefaults {
enum Keys: String, DefaultsKey {
case id // MARK: This uniqueValue conflicts with that of BookDefaults.Keys.id
}
}
BookDefaults().set(5, forKey: .id) // same as: UserDefaults.set(5, forKey: "id")
ComicDefaults().set(10, forKey: .id) // same as: UserDefaults.set(10, forKey: "id")
print(BookDefaults().integer(forKey: .id)!) // -> 10 (not 5)
struct BookDefaults: SafeDefaults {
enum Keys: String, DefaultsKey {
case bookID
}
}
struct ComicDefaults: SafeDefaults {
enum Keys: String, DefaultsKey {
case comicID
}
}
BookDefaults().set(5, forKey: .bookID) // same as: UserDefaults.set(5, forKey: "bookID")
ComicDefaults().set(10, forKey: .comicID) // same as: UserDefaults.set(10, forKey: "comicID")
print(BookDefaults().integer(forKey: .bookID)!) // -> 5
struct BookDefaults: SafeDefaults {
enum Keys: String, DefaultsKey {
case id = "bookID"
}
}
struct ComicDefaults: SafeDefaults {
enum Keys: String, DefaultsKey {
case id = "comicID"
}
}
BookDefaults().set(5, forKey: .id) // same as: UserDefaults.set(5, forKey: "bookID")
ComicDefaults().set(10, forKey: .id) // same as: UserDefaults.set(10, forKey: "comicID")
print(BookDefaults().integer(forKey: .id)!) // -> 5
It is possible to customize key name for UserDefaults by declaring uniqueValue
. For example, you can use your Defaults' name as the namespace.
struct BookDefaults: SafeDefaults {
enum Keys: String, DefaultsKey {
case id
var uniqueValue: String {
// use "BookDefaults.Keys" as the namespace
return "BookDefaults.\(Keys.self).\(self.rawValue)"
}
}
}
struct ComicDefaults: SafeDefaults {
enum Keys: String, DefaultsKey {
case id
var uniqueValue: String {
return "ComicDefaults.\(Keys.self).\(self.rawValue)"
}
}
}
BookDefaults().set(5, forKey: .id) // same as: UserDefaults.set(5, forKey: "BookDefaults.Keys.id")
ComicDefaults().set(10, forKey: .id) // same as: UserDefaults.set(10, forKey: "ComicDefaults.Keys.id")
print(BookDefaults().integer(forKey: .id)!) // -> 5
SafeDefaultsKit is under MIT license. See the LICENSE file for more info.