ReactiveSwift 官方文档学习

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())//回到主线程
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,875评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,569评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,475评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,459评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,537评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,563评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,580评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,326评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,773评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,086评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,252评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,921评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,566评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,190评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,435评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,129评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,125评论 2 352

推荐阅读更多精彩内容

  • 【原文】(15.17) 子曰:“群居终日,言不及义,好行小慧,难矣哉!” 【通译】 孔子说:“整天聚...
    钱江潮369阅读 523评论 1 4
  • 今天工作了一整天,工作人员做的案子有一半是错的,都怪我自己昨天没有去看一份档案内的协议,我太相信他们的工作水平了。...
    浦大魔王76阅读 156评论 0 1
  • 针对九年级化学,学生对于物质的初步认识,化学式化合价学习掌握后,运用化合价书写化学式。利用表格方式,将初中常见化学...
    HX先生阅读 414评论 0 0
  • 不知不觉中,29天的假期已经过去了,许多同学都抱怨时间过得太快了,都在最后几天才来赶。其实呀,如果大家真的按照老...
    杏联陈晓晴阅读 239评论 1 1