SignalKit是一个轻量级的事件和绑定框架。SignalKit的核心是可观察协议。每个可观察协议的实现都定义了观察的类型,因此可观察对象只能发送一种类型的事件。例如,String 类型的可观察对象只能发送String类型的事件。
另一个关键协议是 SignalType,它实现了可观察和可丢弃协议。每个 SignalType 实现都有一个属性 disposableSource: Disposable?
,它指向当前信号之前的可丢弃对象。
因为 SignalType 实现了可丢弃协议,我们可以使用 disposableSource
属性来一起连接映射、过滤和 combineLatest 信号操作。每个操作返回新的 SignalType 或可丢弃对象。当我们对一个 SignalType 调用 dispose()
时,它将丢弃整个操作链。
为了存储操作链,我们可以使用存储属性或可丢弃协议上的 disposeWith(container: DisposableBag) -> Disposable
方法。当 DisposableBag 被解构时,它会自动丢弃它的所有项目。
let disposableBag = DisposableBag()
let userName = Signal<String>()
userName.next { print("name: \($0)") }
.disposeWith(disposableBag)
userName.sendNext("John") // prints "name: John"
SignalKit提供了一种优雅的方式来观察不同的事件源,例如通过一个统一的API通过简单的 observe()
方法调用来观察 KVO、目标操作 和 NSNotificationCenter。观察方法是在 NSObjectProtocol
上的协议扩展,它返回一个带有发送者 Self 的信号事件。然后我们使用面向协议的编程向 SignalEventType 协议添加扩展,其中 Sender 来自给定的类型。
假设我们想观察 class Person: NSObject
的一个实例的 name
属性的变化,使用 KVO。这用 SignalKit 非常简单,只需在实例上调用 observe()
,它将返回此类型的可用事件。然后选择 keyPath(path: String, value: T)
,对于值参数传入属性的初始值。SignalKit 将使用此初始值类型对来自 KVO 的值执行可选类型转换。
let person = Person(name: "John")
person.observe()
.keyPath("name", value: person.name)
.next { print("Hello \($0)") }
.disposeWith(disposableBag)
SignalKit 包含 SignalEventType 扩展,用于继承自 UIControl
和 UIBarButtonItem
的控件。
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)
SignalEventType 还提供了方便的扩展,用于观察 NSNotificationCenter
实例的通知。
let center = NSNotificationCenter.defaultCenter()
center.observe().notification(UIApplicationWillResignActiveNotification)
.next{ _ in print("Resign Active") }
.disposeWith(disposableBag)
SignalKit 中的绑定是通过协议扩展实现的。我们扩展了 SignalType,其中 ObservationType(来自泛型 Observable 协议)是特定类型,并为将值绑定到 UI 控件(如 UILabel
)添加了方法。以下是一个将字符串值从信号绑定到 UILabel 文本属性的示例:
let userName = Signal<String>()
let nameLabel = UILabel()
userName.bindTo(textIn: nameLabel)
.disposeWith(disposableBag)
Signal
是用于发送事件的主体对象,它是线程安全的。
SignalValue
是一个存储其最后发送/当前值的信号。如果我们为其添加新的观察者,它将立即将其值发送给新添加的观察者。如果我们更改信号的价值,它将通知其观察者变化。《SignalValue》也是线程安全的。
let name = SignalValue(value: "John")
name.next { print($0) }.disposeWith(bag) // prints "John"
name.value = "Jonathan" // prints "Jonathan"
我们可以使用类型为 Signal<CollectionEvent>
的信号来发送我们数据源中发生的更改。然后我们可以将信号绑定到 UITableView
或 UICollectionView
,我们发送的更改将反映在表格/集合视图中。
// UsersListViewController
...
viewModel.usersChangeSignal.bindTo(tableView, rowAnimation: .Fade).disposeWith(bag)
// UsersListViewModel
let usersChangeSignal = Signal<CollectionEvent>()
var users = [User]()
...
var event = CollectionEvent()
users.insert(User(name: "John"), atIndex: 0)
event.itemInsertedAt(0, inSection: 0)
usersChangeSignal.sendNext(event)
目前 SignalKit 包含以下 UIKit
组件的扩展:
您可以使用 Keyboard
结构来观察系统发布的关键事件。然后您将获得一个类型为 KeyboardState
的结构,您可以查询键盘的结束/开始框架以及系统与通知一起发送的其他数据。
Keyboard.observe().willShow
.next { print($0.endFrame) }
.disposeWith(disposableBag)
SignalKit 需要 Swift 2.0 和 Xcode 7。
SignalKit 在 MIT 许可下发布。有关更多信息,请参阅 LICENSE.txt 文件。