Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Palau - NSUserDefaults with Wings!

Palau - NSUserDefaults with Wings!

Introduction on Palau. A framework to simplify NSUserDefaults in Swift while adding some extra powers.

https://github.com/symentis/Palau

This presentation was held on Munich iOS Meetup 2016/05/18.
http://www.meetup.com/de-DE/The-Munich-iOS-Developers-Meetup/events/230640835/

Elmar Kretzer

May 18, 2016
Tweet

More Decks by Elmar Kretzer

Other Decks in Programming

Transcript

  1. NSUserDefaults Optimized for storing user settings: NSUserDefaults is intended for

    relatively small amounts of data, queried very frequently, and modified occasionally. Using it in other ways may be slow or use more memory than solutions more suited to those uses. http://dscoder.com/defaults.html
  2. Missing TypeSafety extension NSUserDefaults { // life is too short

    subscript(key: String) -> AnyObject? { get { return NSUserDefaults.standardUserDefaults().objectForKey(key) } set { NSUserDefaults.standardUserDefaults().setObject(newValue, forKey: key) } } } typical usage - somewhere on GitHub
  3. Verbose Workarounds class UserSettings { class var defaultCities: [String] {

    return ["Hamburg", "Berlin", "Munich"] } class var userCityKey: String { return "userCityKey" } class func getUserCities() -> [String] { let userCities = NSUserDefaults.standardUserDefaults() .arrayForKey(UserSettings.userCityKey) if userCities == nil { NSUserDefaults.standardUserDefaults() .setObject(UserSettings.defaultCities, forKey: UserSettings.userCityKey) NSUserDefaults.standardUserDefaults().synchronize() return UserSettings.defaultCities } else { return userCities as! [String] } } typical usage - somewhere on GitHub
  4. Simple import Palau // Define user defaults in an extension

    extension PalauDefaults { // getter and empty setter static var username: PalauDefaultsEntry<String> { get { return value("username") } set { } } }
  5. // what if value is not yet set - any

    fallback? let cities = PalauDefaults.cities.value // -> ["Munich", "London"] // then change PalauDefaults.cities.value = ["Bielefeld"] // -> ["Bielefeld"]
  6. Configurable extension PalauDefaults { // define individual nil fallbacks static

    var cities: PalauDefaultsEntry<[String]> { get { return value("cities").whenNil(use: ["Munich", "London"]) } set { } } }
  7. // shorter please typealias Defaults = PalauDefaults // get initial

    value let secondsA = Defaults.alertTimeSeconds.value // -> 10 // set invalid value Defaults.alertTimeSeconds.value = 8 // get valid value let secondsB = Defaults.alertTimeSeconds.value // -> 10
  8. Versatile // your everyday-Int-checker
 func lessThan(int: Int) -> Int? ->

    Bool { return { $0.map { $0 < int } ?? false } } extension PalauDefaults { // define custom rules static var alertTimeSeconds: PalauDefaultsEntry<Int> { get { return value("alertTimeSeconds") .whenNil(use: 10) .ensure(when: lessThan(10), use: 10) } set { } } }
  9. PalauDefaults.loginDate.value = NSDate() // -> tell s.o. that it changed


    // - to: currentDate
 // - from: previousDate
  10. Observable // simple listener closure receiving new and old value

    let listenChange = { print("changed to", $0, "from", $1) } extension PalauDefaults { // listen to changes static var loginDate: PalauDefaultsEntry<NSDate> { get { return value("loginDate").didSet(listenChange) } set { } } }
  11. // You wanna have a dedicated model-like // struct storing

    a value on year base? var yearSettings = YearSettings(year: 2016) yearSettings.value = 100
  12. Extendable /// create instance for subscript var palauDefaults = PalauDefaults()

    extension PalauDefaults { /// retroactive way of adding init init(){} /// dynamic defaults value, subscript can not be static subscript (valueInYear year: Int) -> PalauDefaultsEntry<Int> { get { return PalauDefaults.value("value-\(year)") } set { } } } // convenience struct model struct YearSettings { let year: Int var value: Int? { get { return palauDefaults[valueInYear: year].value } set { palauDefaults[valueInYear: year].value = newValue } } }
  13. https://github.com/symentis/Palau • Most Standard Types Out-of-the-box • Also supports NSCoding

    and RawRepresentable • Also add your Custom Types (e.g. struct) • Per-property based chain-able Rules • DidSet Observation • 100% Unit Test Coverage