信号 (Signals)

Build Status Cocoapods Compatible Carthage Compatible License Platform Twitter

Signals 是一个用于创建和观察事件的库。它以更强大和优雅的方式取代了委托 (delegates)、动作 (actions) 和 NSNotificationCenter。

特性

要求

安装

要在针对 iOS 7 的项目中使用 Signals,只需将 Signals.swift 复制到您的项目中。

CocoaPods

要将 Signals 集成到您的项目中,请将以下内容添加到您的 Podfile

platform :ios, '8.0'
use_frameworks!

pod 'Signals', '~> 6.0'

Carthage

要使用 Carthage 将 Signals 集成到您的项目中,请将以下内容添加到您的 Cartfile

github "artman/Signals" ~> 6.0

Swift Package Manager

要使用 SwiftPM 将 Signals 集成到您的项目中,请将以下内容添加到您的 Package.swift

dependencies: [
    .package(url: "https://github.com/artman/Signals", from: "6.0.0"),
],

快速开始

通过创建一个或多个信号 (signals) 使类中的事件可观察

class NetworkLoader {

    // Creates a number of signals that can be subscribed to
    let onData = Signal<(data:NSData, error:NSError)>()
    let onProgress = Signal<Float>()

    ...

    func receivedData(receivedData:NSData, receivedError:NSError) {
        // Whenever appropriate, fire off any of the signals
        self.onProgress.fire(1.0)
        self.onData.fire((data:receivedData, error:receivedError))
    }
}

从应用程序的其他地方订阅这些信号

let networkLoader = NetworkLoader("http://artman.fi")

networkLoader.onProgress.subscribe(with: self) { (progress) in
    print("Loading progress: \(progress*100)%")
}

networkLoader.onData.subscribe(with: self) { (data, error) in
    // Do something with the data
}

向 Signals 添加订阅是一个即时添加、无需管理的操作。如果订阅对象被释放,Signal 会取消订阅,因此您无需显式管理订阅的取消。

信号 (Signals) 不仅限于一个订阅者。多个对象可以订阅同一个 Signal。

您也可以在事件发生后订阅它们

networkLoader.onProgress.subscribePast(with: self) { (progress) in
    // This will immediately fire with last progress that was reported
    // by the onProgress signal
    println("Loading progress: \(progress*100)%")
}

高级主题

信号订阅可以应用过滤器 (filters)

networkLoader.onProgress.subscribe(with: self) { (progress) in
    // This fires when progress is done
}.filter { $0 == 1.0 }

您可以对订阅进行采样 (sample up),以限制订阅执行的频率,无论 Signal 触发的频率如何。

networkLoader.onProgress.subscribe(with: self) { (progress) in
    // Executed once per second while progress changes
}.sample(every: 1.0)

默认情况下,订阅在触发 Signal 的线程上同步执行。要更改默认行为,您可以使用 dispatchOnQueue 方法来定义调度队列 (dispatch queue)

networkLoader.onProgress.subscribe(with: self) { (progress) in
    // This fires on the main queue
}.dispatchOnQueue(DispatchQueue.main)

如果您不喜欢触发带有元组 (tuples) 的信号时使用双引号,您可以使用自定义的 => 运算符来触发数据

// If you don't like the double quotes when firing signals that have tuples
self.onData.fire((data:receivedData, error:receivedError))

// You can use the => operator to fire the signal
self.onData => (data:receivedData, error:receivedError)

// Also works for signals without tuples
self.onProgress => 1.0

替换动作 (actions)

Signals 扩展了所有从 UIControl 扩展的类(在 OS X 上不可用),并允许您使用 Signals 监听控制事件,以提高代码的局部性。

let button = UIButton()
button.onTouchUpInside.observe(with: self) {
    // Handle the touch
}

let slider = UISlider()
slider.onValueChanged.observe(with: self) {
    // Handle value change
}

替换委托 (delegates)

Signals 简单且现代,大大减少了设置委托所需的样板代码。

您是否更愿意使用委托来实现回调?

或者使用 Signals 做同样的事情

替换 NotificationCenter

当您的工程师团队壮大时,NotificationCenter 很快就会成为一种反模式。具有隐式数据且没有编译器安全性的全局通知很容易使您的代码容易出错,难以维护和重构。

用 Signals 替换 NotificationCenter 将为您提供由编译器强制执行的强类型安全性,这将帮助您维护代码,无论您移动的速度有多快。

沟通

许可

Signals 是在 MIT 许可下发布的。 有关更多信息,请参见 LICENSE 文件