Awesome
This project is currently in beta and APIs are subject to change.
GenericID
A Swift extension to use string-based API in a type-safe way.
All these fantastic API are compatible with traditional string-based API.
Requirements
- Swift 5.2 (Xcode 11.4)
Type-safe UserDefaults
You can use
NSUbiquitousKeyValueStore
with almost the same API.
1. Define your keys
extension UserDefaults.DefaultKeys {
static let intKey = Key<Int>("intKey")
static let colorKey = Key<Color>("colorKey", transformer: .keyedArchive)
static let pointKey = Key<CGPoint>("pointKey", transformer: .json)
}
2. Have fun!
let ud = UserDefaults.standard
// Get & Set
let value = ud[.intKey]
ud[.stringKey] = "foo"
// Modify
ud[.intKey] += 1
ud[.stringKey] += "bar"
// Typed array
ud[.stringArrayKey].contains("foo")
ud[.intArrayKey][0] += 1
// Work with NSKeyedArchiver
ud[.colorKey] = UIColor.orange
ud[.colorKey]?.redComponent
// Work with JSONEncoder
ud[.pointKey] = CGPoint(x: 1, y: 1)
ud[.pointKey]?.x += 1
// Modern Key-Value Observing
let observation = defaults.observe(.someKey, options: [.old, .new]) { (defaults, change) in
print(change.newValue)
}
// KVO with deserializer
let observation = defaults.observe(.rectKey, options: [.old, .new]) { (defaults, change) in
// deserialized automatically
if let rect = change.newValue {
someView.frame = rect
}
}
// Register with serializer
ud.register(defaults: [
.intKey: 42,
.stringKey: "foo",
.colorKey: UIColor.blue, // serialized automatically
.pointKey: CGPoint(x: 1, y: 1),
])
Default value
If associated type of a key conforms DefaultConstructible
, a default value will be constructed for nil
result.
public protocol DefaultConstructible {
init()
}
Here's types that conforms DefaultConstructible
and its default value:
Type | Default value |
---|---|
Bool | false |
Int | 0 |
Float/Double | 0.0 |
String | "" |
Data | [empty data] |
Array | [] |
Dictionary | [:] |
Optional | nil |
Note: Optional
also conforms DefaultConstructible
, therefore a key typed as DefaultKey<Any?>
aka DefaultKey<Optional<Any>>
will still returns nil
, which is the result of default construction of Optional
.
You can always associate an optional type if you want an optional value.
<!--### Observing-->Type-safe UITableViewCell
/ UICollectionViewCell
1. Define your reuse identifiers
extension UITableView.CellReuseIdentifiers {
static let customCell : ID<MyCustomCell> = "CustomCellReuseIdentifier"
}
2. Register your cells
tableView.register(id: .customCell)
3. Dequeue your cells
let cell = tableView.dequeueReusableCell(withIdentifier: .customCell, for: indexPath)
// Typed as MyCustomCell
XIB-based cells
// That's it!
extension MyCustomCell: UINibFromTypeGettable
// Or, incase your nib name is not the same as class name
extension MyCustomCell: UINibGettable {
static var nibName = "MyNibName"
}
// Then register
tableView.registerNib(id: .customCell)
Type-safe Storyboard
1. Define your storyboards identifiers
extension UIStoryboard.Identifiers {
static let customVC: ID<MyCustomViewController> = "CustomVCStoryboardIdentifier"
}
2. Use It!
// Also extend to get main storyboard
let sb = UIStoryboard.main()
let vc = sb.instantiateViewController(withIdentifier: .customVC)
// Typed as MyCustomViewController
Type-safe Associated Object
// Define your associate keys
extension YourClass.AssociateKeys {
static let someKey: Key<Int> = "someKey"
}
// Use it!
yourObject[.someKey] = 42
License
GenericID is available under the MIT license. See the LICENSE file.