Hello ReactiveSwift(1): 概述 ——(简译)

官方文档:
http://reactivecocoa.io/reactiveswift/docs/latest/index.html
实战项目:
https://github.com/JornWu/ZhiBo_Swift.git


一、什么是ReactiveSwift

ReactiveSwift提供了可组合的、声明性和灵活的围绕“随时间推移的值流”这种宏观概念而创建的实体。
这些实体从根本上是一种监视行为,可用于统一地代表通常Cocoa上和通用的编程模式。如:代理回调闭包通知控制行为事件响应者链未来/承诺KVO
因为这些不同的机制可以用相同方式来都表示。可以把要处理的事情,和监听的事情的代码放在一起,这样非常方便我们管理,就不需要跳到对应的方法里。非常符合我们开发中高聚合,低耦合的思想。

二、核心Reactive实体

1、Signal:单向事件流

Signal的所有者对事件流持有单方面的控制。观察者可以在任何时候注册接收他们所感兴趣的事件。但是这些观察对事件流或者其所有者都没side effect

let channel: Signal<Program, NoError> = tvStation.channelOne
channel.observeValues { program in ... }

2、Event:事件流的基本传输单位

一个Signal可以拥有任意数量的携带着值的Event,这些事件最后跟随着一个特别原因的终止事件。

3、SignalProducer:创建值流的延后工作

SignalProducer延后工作,其输出表示为值流,直到它被启动。每个调用启动SignalProducer,就会创建一个新的Signal,并且延后工作被随后调用。

let frames: SignalProducer<VideoFrame, ConnectionError> = vidStreamer.streamAsset(id: tvShowId)
let interrupter = frames.start { frame in ... }
interrupter.dispose()

4、Lifetime:限制观察的范围

当在观察SignalSignalProducer中,如果不再有对象在观察它们时,其就没必要继续发出值。细想流媒体:只要你停止观看这个视频一次,这个流就会自动通过提供一个Lifetime来关闭。

class VideoPlayer {
  private let (lifetime, token) = Lifetime.make()

  func play() {
    let frames: SignalProducer<VideoFrame, ConnectionError> = ...
    frames.take(during: lifetime).start { frame in ... }
  }
}

5、Property:一个总持有值的可视的容器

Property是一个可看得到其变化的变量。换句话说,其是一个比Signal更有保证的值流,其最新的值总是可用并且这个流永远不会失败。

它就像视频播放的持续更新的当前时间偏移 - 播放总是在任何时候偏移一定的时间,并且随着播放继续,它将会通过播放逻辑被更新。

let currentTime: Property<TimeInterval> = video.currentTime
print("Current time offset: \(currentTime.value)")
currentTime.signal.observeValues { timeBar.timeLabel.text = "\($0)" }

6、Action:一系具有预设事件的行为

当被输入调用时,Action将输入和最新状态应用于预设事件,并将输出推送给任何有兴趣的方。它就像一台自动售货机 - 在选择了插入硬币的选项后,机器会处理订单并最终输出您想要的零食。
请注意,整个过程是相互排斥的 - 您不能同时为两个客户服务。

// Purchase from the vending machine with a specific option.
vendingMachine.purchase
    .apply(snackId)
    .startWithResult { result
        switch result {
        case let .success(snack):
            print("Snack: \(snack)")

        case let .failure(error):
            // Out of stock? Insufficient fund?
            print("Transaction aborted: \(error)")
        }
    }

// The vending machine.
class VendingMachine {
    let purchase: Action<Int, Snack, VendingMachineError>
    let coins: MutableProperty<Int>

    // The vending machine is connected with a sales recorder.
    init(_ salesRecorder: SalesRecorder) {
        coins = MutableProperty(0)
        purchase = Action(state: coins, enabledIf: { $0 > 0 }) { coins, snackId in
            return SignalProducer { observer, _ in
                // The sales magic happens here.
                // Fetch a snack based on its id
            }
        }

        // The sales recorders are notified for any successful sales.
        purchase.values.observeValues(salesRecorder.record)
    }
}

7、参考文献

有关ReactiveSwift中的概念和官方介绍的更多详细信息,请查看以下文档:

Framework Overview
ReactiveSwift官方介绍和实用程序的行为和建议用例的综述。

Basic Operators
提供组合和变换这些元方法的操作的综述。

Design Guidelines
ReactiveSwift元方法的规定和ReactiveSwift最佳实践以及指导如何实现自定义操作。

推荐阅读更多精彩内容