美文网首页
ReactiveSwift 官方文档学习

ReactiveSwift 官方文档学习

作者: 夜雨聲煩_ | 来源:发表于2019-04-15 16:31 被阅读0次

Event

基本构成

event: 事件流的基本传递单元
事件流的构成:任意个value event,以及一个可选的终止事件,包括completedfailedinterrupted。终止以后,就不会在接收。
signalsignalProducersend event

事件形式
  • value event 可以携带多个值,这些值必须同一类型,其他没什么限制。例如value可以表示集合,进度等,甚至可以使用( )表示不关心的内容。
  • failure event 表示失败,内含失败信息,应尽快传递出来以做处理。区别于value event的完成事件,failure event用来表示那些非正常情况下的终止。如果一个事件流不会永远不会失败,可以使用NoError类型,来保证不会被放在stream
  • completed 表示成功或者事件正常结束。可以使用completed来缩短和延长一个事件流的lifetime。例如take可以在接收几个值后过早结束,而其他方法大多是在接收completed时结束。
  • interrupted 表示事件中断。大多方法会立即传递处理,但是也有flattening会忽略interrupted。系统会自动向disposal发送interrupted,当然也可以手动发送,要确保interrupted会被监测并进行处理。`
连续

event是连续的,即使多个线程中同时发生,ReactiveSwift也会保证event按照顺序接收。

递归

就像保证event不会同时传递,也保证value event不会被递归传递。所以operatorsobservers都不可重入(reentrant)。
这是与rac oc版最大的区别
如果一个线程正在处理一个信号,而此时将一个value event传入这个信号,会造成死锁。
注意terminal event是允许被递归发送的,但要配合delay使用,以保证不是一个正在处理的事件发送出来。

同步

信号处理为同步,在结束处理后才继续执行其他。类似于NSNotificationCenterUIControl

Signal

概念

signal:单向的事件流。
原文:A signal is a stream of values that obeys the Event contract.
信号是引用类型,不同的信号有不同的lifetime,可以被终止,一旦终止无法重启。

初始化

信号在初始化完成后开始工作,如果在信号初始化完成前,一样可以发送event,但是无法被接收到。

Observer

Observers:在任何时间地点注册订阅他们所感兴趣的内容,但无法影响内容本身
就像电视信号,你可以收看,但是无法改变其中内容,也无法影响电视信号自身的开始或结束。

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

也就是说,observer的添加和移除并不会影响signal的启动或者停止。只有terminating eventdisposal才会停止signal

多个Observer

类似于电视信号,当多个observer观察同一signal时,这个信号并不会针对某个observer做特殊处理,所有observer都是统一按照事件流顺序进行接收。
只有一个特例,是在信号终止后添加observer会收到interrupted event

生命周期

signal需要一个observer来公开持有,不需要事件流中的event,所有只要有一个active observersignal就会一直retain不会释放。
换句话说,当信号没有被持有和观察,就会被释放掉。

释放

当终止事件信号传入时,所有的observer将会被释放,并且产生的事件也会被处理掉。
最简单的方式是使用disposable

SignalProducer

概念

信号产生器,值类型,像“食谱”一样,只是描述信号如何产生,并只在信号产生后才开始工作。

流程

SignalProducerstartstartWithSignal方法执行时开始产生信号。产生信号后,开始执行SignalProducer初始化时的闭包内容,发送相应信号内容,最后在observer接收到相应内容,并对事件流的内容做相关处理。
虽然SignalProducer并不是真正的执行某项工作,而是被描述为开始或者停止信号产生器,但是这种说法表示将会产生一个信号并开始工作或者停止。

多个observer

信号产生器可以开始多次,并且相应的闭包内容也可以被执行多次。
当两次start绑定两个observer时,相应闭包内容会执行两次,但是每个observer相应监测方法只会被执行一次。
也就是说虽然多个observer绑定在同一个producer以及同一个闭包方法,但实际上由于每次start产生新的signal,所以绑定在不同的signal上,在不同的时间线上分别执行闭包内容。

Lift

使用liftsignal产生signal procueder

Disposable

使用startstartWithSignal来创建signal的同时,会自动产生disposable,通过发送interrupted来中断observer并执行disposable。同时绑定这个新号的其他内容也会被释放。
注意只会影响这个信号本事相应的内容,并不会影响同一个产生器产生的其他信号。

实例

signalProducer: 创建一个带有值的信号流来延迟工作,直到执行start方法。
任意的start方法都会唤醒signalProducer来产生signal,随后执行对应的工作。
这就像一段可选的视频流,你可以决定看什么,什么时间开始看以及什么时间终止。

//定义信号产生器
let frames: SignalProducer<VideoFrame, ConnectionError> = vidStreamer.streamAsset(id: tvShowId)
//信号产生器开始执行产生信号并返回一个中断者(用来随时中断)
let interrupter = frames.start { frame in ... }
//停止
interrupter.dispose()

Property

概念

property是含有初始值的一种信号,与所绑定值的关系比signal更加牢固,总可以监测并获取到值的最新状态,并且不会失败。始终观察某值变化,类似于KVO
类似于视频播放时候随时更新的视频时间进度条。

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

property必须能够获取或者存储属性的最新值,并且通过propertyProtocol.value访问。pbserver相当于didset observer

composed property

注意property绑定属性不会影响到源属性,这点类似于绑定观察信号不会影响源信号一样。
composed property没有自己的lifetime,并且他的释放不会影响到相应的signal或者producer

Action

action: 预设行动完成连串工作。
当被一个输入唤醒时,传入这个输入的最新状态,并通过一连串的处理返回想要的结果。
这像一个自动贩卖机,投入硬币,选择想要的东西,需要注意的是一台贩卖机不能同时服务两位客人。

// Purchase from the vending machine with a specific option.
//VC中调用,传参,UI处理返回结果。
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 {
    //定义viewmodel中提供购买请求接口
    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)
    }
}

LifeTime

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 ... }
  }
}

官方例子

//定义string类型信号监测textfield中变化值,实际为Signal<String?, Result.NoError>类型
let searchStrings = textField.reactive.continuousTextValues
//搜索结果 数组
let searchResults = searchStrings
    .flatMap(.latest) { (query: String?) -> SignalProducer<(Data, URLResponse), AnyError> in
        //第一步筛选返回signalProducer
        let request = self.makeSearchRequest(escapedQuery: query)
        return URLSession.shared.reactive.data(with: request)
    }
    .map { (data, response) -> [SearchResult] in
        //第二步筛选返回结果数组
        let string = String(data: data, encoding: .utf8)!
        return self.searchResults(fromJSONString: string)
    }
    .observe(on: UIScheduler())//回到主线程

相关文章

网友评论

      本文标题:ReactiveSwift 官方文档学习

      本文链接:https://www.haomeiwen.com/subject/vqwuwqtx.html