Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/symentis/Palau
NSUserDefaults with Wings!
https://github.com/symentis/Palau
nsuserdefaults swift
Last synced: 3 days ago
JSON representation
NSUserDefaults with Wings!
- Host: GitHub
- URL: https://github.com/symentis/Palau
- Owner: symentis
- License: apache-2.0
- Created: 2016-04-26T07:09:42.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2017-09-26T15:00:58.000Z (about 7 years ago)
- Last Synced: 2024-10-14T10:58:13.707Z (20 days ago)
- Topics: nsuserdefaults, swift
- Language: Swift
- Homepage:
- Size: 273 KB
- Stars: 386
- Watchers: 6
- Forks: 19
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-swift - Palau - Typesafe NSUserDefaults with custom rules. (Libs / Data Management)
README
[![Build Status](https://travis-ci.org/symentis/Palau.svg?branch=master)](https://travis-ci.org/symentis/Palau)
[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Palau.svg)](https://img.shields.io/cocoapods/v/Palau)
[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
[![Platform](https://img.shields.io/cocoapods/p/Palau.svg?style=flat)](http://cocoadocs.org/docsets/Palau)
[![swiftyness](https://img.shields.io/badge/pure-swift-ff3f26.svg?style=flat)](https://swift.org/)
[![@elmkretzer](https://img.shields.io/badge/[email protected]?style=flat)](http://twitter.com/elmkretzer)
[![@madhavajay](https://img.shields.io/badge/[email protected]?style=flat)](http://twitter.com/madhavajay)#Palau: NSUserDefaults with Wings!
-------
Features |
Included Types |
Installation |
Validators and Defaults |
Custom Types |
DidSet Callback |
-------## Features
- [x] Easily store your Custom Types in NSUserDefaults
- [x] Most Standard Types Out-of-the-box
- [x] Per-property based Chainable Rules
- [x] Supports NSCoding and RawRepresentable
- [x] 300% Type Safe :P
- [x] 100% Unit Test Coverage
- [x] Swift 3 features coming!## Already Included Types
### Swift
- [x] Bool
- [x] Int
- [x] UInt
- [x] Float
- [x] Double
- [x] String
- [x] Array
- [x] Dictionary### Foundation
- [x] NSNumber
- [x] NSString
- [x] NSArray
- [x] NSDictionary
- [x] NSDate
- [x] NSData
- [x] UIColor## Requirements
- Swift 2.2
- iOS 8.0+ / tvOS 9.0+ / watchOS 2.0+
- Xcode 7.3+## Installation
### Carthage
To integrate Palau into your project using Carthage, add to your `Cartfile`:
```ogdl
github "symentis/Palau" ~> 1.0
```Run `carthage update` to build the framework and drag the built `Palau.framework` into your Xcode project.
See more instructions on the [Carthage page](https://github.com/Carthage/Carthage).### CocoaPods
To integrate Palau into your project using CocoaPods, add to your `Podfile`:
```ruby
use_frameworks!pod 'Palau', '~> 1.0'
```Run `pod install` to install the framework into your Xcode workspace.
## Usage
Import Palau```swift
import Palau
```Once you import the framework you can setup PalauDefaults like:
```swift
/// Your defaults are defined as extension of PalauDefaults
///
/// - The generic type of your PalauDefaultsEntry must conform
/// to the protocol PalauDefaultable.
/// - We provide support for the most common types.
/// - `value` is a helper function defined in PalauDefaults
/// - The String "backingName" is the key used in NSUserDefaults
/// - The empty `set` is used to please the compiler
extension PalauDefaults {
/// a NSUserDefaults Entry of Type String with the key "backingName"
public static var name: PalauDefaultsEntry {
get { return value("backingName") }
set { }
}
}
```### Set
Every value of a `PalauDefaultsEntry` will always be optional.
If you want to set a value you call:```swift
PalauDefaults.name.value = "I am a great String value!"
```### Get
Getting your value back is as easy as:
```swift
/// name is an Optional
let name = PalauDefaults.name.value
```### Delete
You can delete a property by setting it to `nil`:
```swift
PalauDefaults.name.value = nil
```
Or
```swift
/// skip custom rules and delete
PalauDefaults.name.clear()
```## Custom Rules
### Providing a Default Value
If you want to provide a default, when there is no value set,
you can write a custom rule. This allows fine granular control on
your values.We include two rule types by default: `whenNil` and `ensure`
```swift
import Palau
extension PalauDefaults {
public static var color: PalauDefaultsEntry {
/// whenNil provides a value that will be returned
/// when the related NSUserDefaults value is nil
/// (e.g. the 1st time, or after clear)
get { return value("color").whenNil(use: UIColor.redColor()) }
set { }
}
}/// is UIColor.redColor()
let color: UIColor? = PalauDefaults.color.value
```### Providing a Validator
You can also build up arbitrary rules for your value like:
```swift
/// Custom Validator Closure
let lessThan10: Int? -> Bool = {
return $0.map { $0 < 10 } ?? false
}/// the PalauDefaultsEntry with the key "intValueMin10" has 2 rules
/// - 1. when the value is nil - we will get or set 10
/// - 2. when the value is less than 10 (see lessThan10 closure) - we will also get or set 10
/// - Add as many chainable rules as you like
public static var intValueMin10: PalauDefaultsEntry {
get { return value("intValue")
.whenNil(use: 10)
.ensure(when: lessThan10, use: 10) }
set { }
}/// try setting the property to 8
PalauDefaults.intValueMin10.value = 8
/// property ensured to be >= 10
assert(PalauDefaults.intValueMin10.value == 10)
/// try setting the property to 11
PalauDefaults.intValueMin10.value = 11
/// property changed to 11
assert(PalauDefaults.intValueMin10.value == 11)
```## Custom Types
In Swift 2.2 Classes and Protocols can be used to constrain the ValueType.
For example this is how Palau adds support for `RawRepresentable` via an Extension:```swift
/// Extension for RawRepresentable types aka enums
extension PalauDefaultable where ValueType: RawRepresentable {public static func get(key: String, from defaults: NSUD) -> ValueType? {
guard let val = defaults.objectForKey(key) as? ValueType.RawValue else { return nil }
return ValueType(rawValue: val)
}public static func set(value: ValueType?, forKey key: String, in defaults: NSUD) -> Void {
guard let value = value?.rawValue as? AnyObject else { return defaults.removeObjectForKey(key) }
defaults.setObject(value, forKey: key)
}
}
```Generally for Types which conform to `NSCoding` you can usually just provide an
extension like so:```swift
/// Make UIColor PalauDefaultable
extension UIColor: PalauDefaultable {
public typealias ValueType = UIColor
}
```## Look Mum, even Structs!
For custom types you can provide an extension on your type for `PalauDefaultable`,
to implement a `get` and a `get` function.```swift
// example Struct called Structy for demonstrating we can save a Struct with Palau
public struct Structy {
let tuple: (String, String)
}// our Structy PalauDefaultable extension allowing the mapping between PalauDefaults and the Type
// here we just map the two values to two keys named "1" and "2"
extension Structy: PalauDefaultable {
public static func get(key: String, from defaults: NSUD) -> Structy? {
guard let d = defaults.objectForKey(key) as? [String: AnyObject] ,
let t1 = d["1"] as? String,
let t2 = d["2"] as? String else { return nil }
return Structy(tuple: (t1, t2))
}public static func set(value: Structy?, forKey key: String, in defaults: NSUD) -> Void {
guard let value = value else { return defaults.setObject(nil, forKey: key) }
defaults.setObject(["1": value.tuple.0, "2": value.tuple.1], forKey: key)
}
}// now create a property on PalauDefaults
extension PalauDefaults {
public static var structWithTuple: PalauDefaultsEntry {
get { return value("structy") }
set { }
}
}
```## DidSet Callback
You can easily register a `didSet` callback, which gets fired when the value has changed.
```swift
extension PalauDefaults {
public static var strings: PalauDefaultsEntry<[String]> {
get { return value("strings").didSet({ print("changed to:", $0, "from:", $1) }) }
set { }
}
}
```## Limitations for Swift 2.2
We are waiting for more Swift 3 generics features like extensions on Generic types.... yay!
Then we get even more type saftey on arrays and dictionaries.
Plus we might be able to make generic types conform to `PalauDefaultable`.## FAQ
### What's the origin of the name Palau?
Palau is named after the [Palau swiftlet](https://en.wikipedia.org/wiki/Palau_swiftlet), a species of swift, endemic to the island of Palau.
Btw - if you really don\`t like the name, you can use a `typealias`
```swift
typealias Defaults = PalauDefaults
typealias Defaultable = PalauDefaultable
/// for Swift 3 even:
/// typealias DefaultsEntry = PalauDefaultsEntry
```---
## Credits
Palau is owned and maintained by [Symentis GmbH](http://symentis.com).Developed by: Elmar Kretzer & Madhava Jay
Follow for more Swift Goodness:
[![Twitter](https://img.shields.io/badge/[email protected]?style=flat)](http://twitter.com/elmkretzer)
[![Twitter](https://img.shields.io/badge/[email protected]?style=flat)](http://twitter.com/madhavajay)##Logo
Awesome Logo by: [4th motion](http://4thmotion.com)
## String Test Fixtures
[Markus Kuhn](http://www.cl.cam.ac.uk/~mgk25/)## License
Palau is released under the Apache 2.0 license. See LICENSE for details.