Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/yankodimitrov/SignalKit
SignalKit is a reactive Swift framework with focus on clean and readable API.
https://github.com/yankodimitrov/SignalKit
observer protocol-oriented reactive signal swift unidirectional
Last synced: about 1 month ago
JSON representation
SignalKit is a reactive Swift framework with focus on clean and readable API.
- Host: GitHub
- URL: https://github.com/yankodimitrov/SignalKit
- Owner: yankodimitrov
- License: mit
- Created: 2015-07-15T11:42:05.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2017-03-07T09:18:30.000Z (almost 8 years ago)
- Last Synced: 2024-10-01T09:04:33.532Z (2 months ago)
- Topics: observer, protocol-oriented, reactive, signal, swift, unidirectional
- Language: Swift
- Homepage:
- Size: 885 KB
- Stars: 258
- Watchers: 7
- Forks: 18
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
- awesome-swift-cn - SignalKit - Swift event and binding framework. (Libs / Events)
README
---
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)## Abstract
SignalKit is a lightweight event and binding framework. The core of SignalKit is the Observable protocol. Each implementation of the Observable protocol defines the type of the observation thus an Observable can sendNext only one type of event. For example an Observable of type String can only sendNext String values.Another key protocol is SignalType which implements Observable and Disposable. Each SignalType implementation has a property
disposableSource: Disposable?
which points to a Disposable that comes before the current signal.Because SignalType implements Disposable we can use the
disposableSource
property to chain signal operations like map, filter and combineLatest together. Each operation returns either a new SignalType or a Disposable. When we calldispose()
on a SignalType it will dispose the whole chain of operations.To store the chain of operations we can use a stored property or the
disposeWith(container: DisposableBag) -> Disposable
method on the Disposable protocol. When DisposableBag is deinitialized it will dispose all of its items for us.```swift
let disposableBag = DisposableBag()
let userName = Signal()userName.next { print("name: \($0)") }
.disposeWith(disposableBag)userName.sendNext("John") // prints "name: John"
```![SignalKit Primary Protocols](https://raw.githubusercontent.com/yankodimitrov/SignalKit/SignalKit-4.0/Resources/primary-protocols.png)
## Events And Bindings
SignalKit comes with an elegant way to observe for different event sources like **KVO**, **Target Action** and **NSNotificationCenter** via an unified API by simply calling
observe()
method. The observe method is a protocol extension on theNSObjectProtocol
which returns a SignalEvent with sender Self. Then we use Protocol Oriented Programming to add extensions to a SignalEventType protocol where Sender is from a given type.![SignalKit Primary Protocols](https://raw.githubusercontent.com/yankodimitrov/SignalKit/SignalKit-4.0/Resources/event-model.png)
### Key Value Observing
Let's say we want to observe an instance of
class Person: NSObject
for it'sname
property changes with KVO. This is super easy with SignalKit, just callobserve()
on the instance and it will return the available events for this type. Then choosekeyPath(path: String, value: T)
where for the value parameter pass the initial value of the property. SignalKit will use this initial value type to perform an optional type cast on the values sent by KVO.```swift
let person = Person(name: "John")person.observe()
.keyPath("name", value: person.name)
.next { print("Hello \($0)") }
.disposeWith(disposableBag)
```### Target Action
SignalKit comes with SignalEventType extensions for controls which inherits from
UIControl
andUIBarButtonItem
:```swift
let control = UIControl()
let barButton = UIBarButtonItem()control.observe().events([.TouchUpInside])
.next { _ in print("Tap!") }
.disposeWith(disposableBag)
barButton.observe().tapEvent
.next { _ in print("Tap!") }
.disposeWith(disposableBag)
```### NSNotificationCenter
SignalEventType also have a handy extensions for observing an instance of
NSNotificationCenter
for notifications:```swift
let center = NSNotificationCenter.defaultCenter()center.observe().notification(UIApplicationWillResignActiveNotification)
.next{ _ in print("Resign Active") }
.disposeWith(disposableBag)
```### Bindings
Bindings in SignalKit are implemented again with protocol extensions. We extend the SignalType where the ObservationType (from the generic Observable protocol) is from a certain type and add method to bind the value to a UI control like
UILabel
.
Here is an example of binding the String value from the signal to the text property of UILabel:```swift
let userName = Signal()
let nameLabel = UILabel()userName.bindTo(textIn: nameLabel)
.disposeWith(disposableBag)
```## Signals
#### Signal
Signal
is the primary object which you can use to send events and it is thread safe.#### SignalValue
SignalValue
is a signal that stores its last sent/current value. If we add a new observer to it it will send immediately its value to the newly added observer. If we change the value of the signal it will notify its observers for the change.SignalValue
is also thread safe.```swift
let name = SignalValue(value: "John")name.next { print($0) }.disposeWith(bag) // prints "John"
name.value = "Jonathan" // prints "Jonathan"
```#### CollectionEvent
We can use a signal of typeSignal<CollectionEvent>
to send the changes that occur in our data source. Then we can bind the signal toUITableView
orUICollectionView
and the changes that we send will be reflected in the table/collection view:```swift
// UsersListViewController
...
viewModel.usersChangeSignal.bindTo(tableView, rowAnimation: .Fade).disposeWith(bag)// UsersListViewModel
let usersChangeSignal = Signal()
var users = [User]()
...var event = CollectionEvent()
users.insert(User(name: "John"), atIndex: 0)
event.itemInsertedAt(0, inSection: 0)usersChangeSignal.sendNext(event)
```## Operations
SignalKit comes with the following SignalType operations:
![SignalKit Primary Protocols](https://raw.githubusercontent.com/yankodimitrov/SignalKit/SignalKit-4.0/Resources/signal-operations.png)## Extensions
Currently SignalKit comes with extensions for the the following
UIKit
components:
![SignalKit Primary Protocols](https://raw.githubusercontent.com/yankodimitrov/SignalKit/SignalKit-4.0/Resources/uikit-extensions.png)### Keyboard
You can use theKeyboard
structure to observe for keyboard events posted by the system. Then you will get back a structure of typeKeyboardState
which you can query for the keyboard end/start frame and other data that the system sends with the notification:```swift
Keyboard.observe().willShow
.next { print($0.endFrame) }
.disposeWith(disposableBag)
```## Installation
SignalKit requires Swift 2.0 and Xcode 7
#### Carthage
Add the following line to your [Cartfile](https://github.com/carthage/carthage)
```swift
github "yankodimitrov/SignalKit" "master"
```#### CocoaPods
Add the following line to your [Podfile](https://guides.cocoapods.org/)
```swift
pod “SignalKit”
```##License
SignalKit is released under the MIT license. See the LICENSE.txt file for more info.