Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/blendle/hanson
Lightweight observations and bindings in Swift
https://github.com/blendle/hanson
binding kvc kvo observation swift
Last synced: 2 days ago
JSON representation
Lightweight observations and bindings in Swift
- Host: GitHub
- URL: https://github.com/blendle/hanson
- Owner: blendle
- License: isc
- Created: 2017-01-31T10:53:07.000Z (almost 8 years ago)
- Default Branch: master
- Last Pushed: 2021-10-25T21:29:58.000Z (about 3 years ago)
- Last Synced: 2024-04-23T19:19:17.437Z (8 months ago)
- Topics: binding, kvc, kvo, observation, swift
- Language: Swift
- Size: 49.8 KB
- Stars: 518
- Watchers: 20
- Forks: 18
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
## What is Hanson?
Hanson is a simple, lightweight library to observe and bind values in Swift. It's been developed to support the MVVM architecture in our [Blendle iOS app](https://itunes.apple.com/nl/app/blendle/id947936149). Hanson provides several advantages to using KVO in Swift, such as a Swiftier syntax, no boilerplate code, and the ability to use it in pure Swift types.
## Example Usage
The most basic use case is to simply observe an `Observable` for changes:
```swift
let observable = Observable("Hello World")
observe(observable) { event in
// Invoked whenever observable.value is set.
print("Value changed from \(event.oldValue) to \(event.newValue)")
}
```Hanson also provides a wrapper around KVO, so you can do the following to observe a `UITextField`'s `text` property for changes:
```swift
let textField = UITextField()
let textFieldObservable = textField.dynamicObservable(keyPath: #keyPath(UITextField.text), type: String.self)
observe(textFieldObservable) { event in
print("Text field value changed from \(event.oldValue) to \(event.newValue)")
}
```Furthermore, you can also use Hanson to bind an observable to another observable. Let's say we have a view model that's responsible for loading data, and we want the view to show an activity indicator while the view model is loading data:
```swift
class ViewModel {let isLoadingData = Observable(false)
}
class View {
let showsActivityIndicator = Observable(false)
}
let viewModel = ViewModel()
let view = View()
bind(viewModel.isLoadingData, to: view.showsActivityIndicator)
```Now, whenever the view model's `isLoadingData` property is set to a different value, it will automatically be set to the view's `showsActivityIndicator` property.
Binding is also supported from and to KVO-backed observables. To bind a text field's content to a label:
```swift
let textField = UITextField()
let textFieldObservable = textField.dynamicObservable(keyPath: #keyPath(UITextField.text), type: String.self)let label = UILabel()
let labelObservable = label.dynamicObservable(keyPath: #keyPath(UILabel.text), type: String.self)bind(textFieldObservable, to: labelObservable)
```If you want to handle the binding yourself, you can also provide a closure that will be invoked when a new value should be set. In the following example, we'll bind an `isLoadingData` observable to a `UIActivityIndicatorView`:
```swift
let isLoadingData = Observable(false)
let activityIndicatorView = UIActivityIndicatorView()
bind(isLoadingData, to: activityIndicatorView) { activityIndicatorView, isLoadingData in
if isLoadingData {
activityIndicatorView.startAnimating()
} else {
activityIndicatorView.stopAnimating()
}
}
```Hanson also supports observering notifications sent through a `NotificationCenter`. For example, to observe when an application is entering the background:
```swift
let observable = NotificationCenter.default.observable(for: Notification.Name.UIApplicationDidEnterBackground)
observe(observable) { notification in
print("Application did enter background")
}
```### Schedulers
Schedulers can be used to schedule the events of your observation. By default, Hanson uses the `CurrentThreadScheduler`, which immediatly sends events on whatever thread it currently is. Hanson also offers the `MainThreadScheduler`, which ensures events are sent on the main thread. This is useful when observing a value that can change from a background thread and you want to do UI changes based on that value. For example:
```swift
let observable = Observable("Hello World")
observe(observable, with: MainThreadScheduler()) { event in
// It's safe to do UI work here without calling DispatchQueue.main.async here
}performOnBackground {
observable.value = "Hello from a background"
}
```Schedulers are also supported when binding observables:
```swift
let isLoadingData = Observable(true)
let activityIndicatorView = UIActivityIndicatorView()
bind(isLoadingData, with: MainThreadScheduler(), to: activityIndicatorView) { activityIndicatorView, isLoadingData in
// It's safe to do UI work here without calling DispatchQueue.main.async here
}performOnBackground {
isLoadingData.value = false
}
```You can create your own scheduler by conforming to the `EventScheduler` protocol.
## Requirements
* iOS 8.0+ / macOS 10.9+ / tvOS 9.0+
* Xcode 8## Installation
Hanson is available through either [CocoaPods](http://cocoapods.org) or [Carthage](https://github.com/Carthage/Carthage).
### Cocoapods
1. Add `pod 'Hanson'` to your `Podfile`.
2. Run `pod install`.### Carthage
1. Add `github 'blendle/Hanson'` to your `Cartfile`.
2. Run `carthage update`.
3. Link the framework with your target as described in [Carthage Readme](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application).### Swift Package Manager
1. In Xcode, select your project and scroll to `Frameworks, Libraries, and Embedded Content`.
2. Click the `+`.
3. At the bottom of the frameworks and libraries window that opens, select `Add other...` and then `Add package dependency...`.
4. Paste `https://github.com/blendle/Hanson.git` in the search textfield and follow through with the assistant.## Building
The project obviously builds fine through Xcode, just load up `Hanson.xcodeproj` and run it.
For convenience, we've included a few scripts and a `Makefile` that allow you to build Hanson from the command line and through continuous integration. They are inspired by GitHub's [Scripts to Rule Them All](https://github.com/github/scripts-to-rule-them-all) boilerplate:
```
|-- script/
|-- etc/
|-- config.sh # Contains basic configuration parameters
|-- bootstrap # Prepares the project
|-- setup # Sets up the local building process
|-- test # Runs tests locally
|-- cisetup # Sets up the CI building process
|-- citest # Runs tests in a CI environment
```To get started:
`$ make`
To skip setup and immediately start testing:
`$ make test`
Make sure all tests pass before opening a Pull Request.
## Release Notes
See [CHANGELOG.md](https://github.com/blendle/Hanson/blob/master/CHANGELOG.md) for a list of changes.
## License
Hanson is released under the ISC license. See [LICENSE](https://github.com/blendle/Hanson/blob/master/LICENSE) for details.