Prephirences
Prephirences is a Swift library that provides useful protocols and convenience methods to manage application preferences, configurations and app-state. UserDefaults
Install / Use
/learn @phimage/PrephirencesREADME
Prephirences - Preϕrences
<a href="https://www.patreon.com/phimage"> <img src="https://c5.patreon.com/external/logo/become_a_patron_button.png" alt="Become a Patron!" height="35"> </a> <a href="https://paypal.me/ericphimage"> <img src="https://buymecoffee.intm.org/img/button-paypal-white.png" alt="Buy me a coffee" height="35"> </a><img align="left" src="logo.png" hspace="20"> Prephirences is a Swift library that provides useful protocols and convenience methods to manage application preferences, configurations and app-state.
@Preference(key: "enabled")
var enabled: Bool?
@UserDefaultsPreference(key: "my.string.pref")
var pref: String?
@MutablePreference(preferences: UserDefaults.standard, key: "enabled")
var enabled: Bool?
let userDefaults = UserDefaults.standard
if let enabled = userDefaults["enabled"] as? Bool {..}
userDefaults["mycolorkey", archive] = UIColor.blue
Preferences is not only UserDefaults, it could be also :
- Keychain to store credential
- Any dictionary
- Application information from
Bundle - File stored preferences (ex: plist)
- iCloud stored preferences
NSUbiquitousKeyValueStore - or your own private application preferences
ie. any object which implement the simple protocol PreferencesType, which define key value store methods.
You can also combine multiples preferences and work with them transparently (see Composing)
Contents
- Usage
- Setup
- Logo
Usage
Creating
The simplest implementation of PreferencesType is DictionaryPreferences
// From Dictionary
var fromDico = DictionaryPreferences(myDictionary)
// or literal
var fromDicoLiteral: DictionaryPreferences = ["myKey": "myValue", "bool": true]
// From filepath
if let fromFile = DictionaryPreferences(filePath: "/my/file/path") {..}
// ...in main bundle ##
if let fromFile = DictionaryPreferences(filename: "prefs", ofType: "plist") {..}
Accessing
You can access with all methods defined in PreferencesType protocol
if let myValue = fromDicoLiteral.object(forKey: "myKey") {..}
if let myValue = fromDicoLiteral["bool"] as? Bool {..}
var hasKey = fromDicoLiteral.hasObject(forKey: "myKey")
var myValue = fromDicoLiteral.bool(forKey: "myKey")
..
If you want to access using RawRepresentable enum.
enum MyKey: PreferenceKey/*String*/ {
case Key1, Key2, ...
}
if let myValue = fromDicoLiteral.object(forKey: MyKey.Key1) {..}
var myValue = fromDicoLiteral.bool(forKey: MyKey.Key2)
:warning: RawRepresentableKey must be imported, see setup.
Modifying
Modifiable preferences implement the protocol MutablePreferencesTypes
The simplest implementation is MutableDictionaryPreferences
var mutableFromDico: MutableDictionaryPreferences = ["myKey": "myValue"]
mutableFromDico["newKey"] = "newValue"
mutableFromDico.set("myValue", forKey: "newKey")
mutableFromDico.set(true, forKey: "newKey")
...
You can append dictionary or other PreferencesType using operators
mutableFromDico += ["newKey": "newValue", "otherKey": true]
You can also remove one preference
mutableFromDico -= "myKey"
Apply operators to one preference
You can extract a MutablePreference from any MutablePreferencesTypes and apply operators according to its value type
var intPref: MutablePreference<Int> = aPrefs.preference(forKey: "intKey")
var intPref: MutablePreference<Int> = aPrefs <| "intKey"
intPref++
intPref--
intPref += 30
intPref -= 30
intPref *= 20
intPref %= 7
intPref /= 3
switch(intPref) {
case 1: println("one")
case 2...10: println("not one or zero but...")
default: println("unkwown")
}
var boolPref: MutablePreference<Bool> = aPrefs <| "boolKey")
boolPref &= false
boolPref |= true
boolPref != true
You can also use some methods to change value
var stringPref: MutablePreference<String> = userDefaults <| "stringKey"
stringPref.apply { value in
return value?.uppercaseString
}
or transform the value type using closures
let intFromBoolPref : MutablePreference<Int> = boolPref.transform { value in
return (value ?? false) ? 1:0
}
Transformation and archiving
Before storing or accessing the value, transformation could be applied, which conform to protocol PreferenceTransformation.
This allow to archive, to change type, return default value if nil and many more.
You can get and set value using subscript
userDefaults["aKey", myTransformation] = myObject
if let object = userDefaults["aKey", myTransformation] {...}
If you extract one preference, use transformation property to setup the transformation
var aPref: MutablePreference<MyObject> = userDefaults <| "aKey"
aPref.transformation = myTransformation
or you can use some utility functions to specify a default value when the stored value match a condition
public var intValueMin10: MutablePreference<Int> {
get {
return userDefaults.preference(forKey: "intKey")
.whenNil(use: 100)
.ensure(when: lessThan100, use: 100)
}
set {..}
}
Archiving
Archiving is particularly useful with NSUserDefaults because NSUserDefaults can't store all type of objects.
The following functions could help by transforming the value into an other type
You can archive into Data using this two methods
userDefaults.set(objectToArchive: UIColor.blueColor(), forKey: "colorKey")
userDefaults["colorKey", .Archive] = UIColor.blueColor()
and unarchive using
if let color = userDefaults.unarchiveObject(forKey: "colorKey") as? UIColor {..}
if let color = userDefaults["colorKey", .Archive] as? UIColor {..}
If you extract one preference, use transformation property to setup archive mode
var colorPref: MutablePreference<UIColor> = userDefaults <| "colorKey"
colorPref.transformation = TransformationKey.Archive
colorPref.value = UIColor.redColor()
if let color = colorPref.value as? UIColor {..}
NSValueTransformer
You can also apply for all objects type an NSValueTransformer, to transform into JSON for instance
userDefaults["colorKey", myValueTransformerToJson] = myComplexObject
if let object = userDefaults["colorKey", myValueTransformerToJson] {...}
:warning: allowsReverseTransformation must return true
Store RawRepresentable objects
For RawRepresentable objects like enum you can use the computed attribute preferenceTransformation as transformation
enum PrefEnum: String {
case One, Two, Three
}
var pref: MutablePreference<PrefEnum> = preferences <| "enumKey"
pref.transformation = PrefEnum.preferenceTransformation
pref.value = PrefEnum.Two
Some implementations
UserDefaults
UserDefaults implement PreferencesType and can be acceded with same methods
let userDefaults = UserDefaults.standard
if let myValue = userDefaults["mykey"] as? Bool {..}
NSUserDefaults implement also MutablePreferencesType and can be modified with same methods
userDefaults["mykey"] = "myvalue"
// with type to archive
userDefaults["mykey", .Archive] = UIColor.blueColor()
Bundle
All Bundle implement PreferencesType, allowing to access Info.plist file.
For instance the Bundle.main contains many useful informations about your application.
Prephirences framework come with some predefined enums described in apple documentations and defined in `PropertyListKeys
