RxSwift系列(一)Observable、Observer、Subjects

一、基本介绍&安装配置

1.Rx是 ReactiveX 的缩写,简单来说就是基于异步 Event(事件)序列的响应式编程。Rx 可以简化异步编程方法,并提供更优雅的数据绑定。让我们可以时刻响应新的数据同时顺序地处理它们。Rx是一种跨平台标准,目前已经有许多基于不同开发语言的 Rx 的库,RxSwift, RxJava, RxJS, RxKotlin等。

2.安装配置

# Podfile
use_frameworks!

target 'YOUR_TARGET_NAME' do
    pod 'RxSwift',    '~> 4.0'
    pod 'RxCocoa',    '~> 4.0'
end

RxSwift:它只是基于 Swift 语言的 Rx 标准实现接口库,所以 RxSwift 里不包含任何 Cocoa 或者 UI方面的类。
RxCocoa:是基于 RxSwift针对于 iOS开发的一个库,它通过 Extension 的方法给原生的比如 UI 控件添加了 Rx 的特性,使得我们更容易订阅和响应这些控件的事件。

二、函数式编程VS传统编程

以实现一个tableView列表展示歌曲名字和歌手名字,点击tableView item打印出对应的歌曲和歌手名字为例

1.Model

import UIKit

//歌曲结构体
struct Music {
    let name: String //歌名
    let singer: String //演唱者

    init(name: String, singer: String) {
        self.name = name
        self.singer = singer
    }
}

//实现 CustomStringConvertible 协议,方便输出调试
extension Music: CustomStringConvertible {
    var description: String {
        return "name:\(name) singer:\(singer)"
    }
}

2.ViewModel

import Foundation

//歌曲列表数据源
struct MusicListViewModel {
    let data = [
        Music(name: "无条件", singer: "陈奕迅"),
        Music(name: "你曾是少年", singer: "S.H.E"),
        Music(name: "从前的我", singer: "陈洁仪"),
        Music(name: "在木星", singer: "朴树"),
    ]
}
import RxSwift

//歌曲列表数据源
struct MusicListViewModel {
    let data = Observable.just([
        Music(name: "无条件", singer: "陈奕迅"),
        Music(name: "你曾是少年", singer: "S.H.E"),
        Music(name: "从前的我", singer: "陈洁仪"),
        Music(name: "在木星", singer: "朴树"),
    ])
}

//这里我们将 data 属性变成一个可观察序列对象(Observable Squence),对象当中的内容是完全一样的。
//“序列”可以对这些数值进行“订阅(Subscribe)”,有点类似于“通知(NotificationCenter)”。


3.ViewController

import UIKit
import RxSwift

class ViewController: UIViewController {

    //tableView对象
    @IBOutlet weak var tableView: UITableView!

    //歌曲列表数据源
    let musicListViewModel = MusicListViewModel()

    override func viewDidLoad() {
        super.viewDidLoad()

        //设置代理
        tableView.dataSource = self
        tableView.delegate = self
    }
}

extension ViewController: UITableViewDataSource {
    //返回单元格数量
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return musicListViewModel.data.count
    }

    //返回对应的单元格
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
    -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "musicCell")!
        let music = musicListViewModel.data[indexPath.row]
        cell.textLabel?.text = music.name
        cell.detailTextLabel?.text = music.singer
        return cell
    }
}

extension ViewController: UITableViewDelegate {
    //单元格点击
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("你选中的歌曲信息【\(musicListViewModel.data[indexPath.row])】")
    }
}
import UIKit
import RxSwift
import RxCocoa

class ViewController: UIViewController {

    //tableView对象
    @IBOutlet weak var tableView: UITableView!

    //歌曲列表数据源
    let musicListViewModel = MusicListViewModel()

    //负责对象销毁
    let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

        //将数据源数据绑定到tableView上
        musicListViewModel.data
        .bind(to: tableView.rx.items(cellIdentifier:"musicCell")) { _, music, cell in
               cell.textLabel?.text = music.name
               cell.detailTextLabel?.text = music.singer
         }.disposed(by: disposeBag)

        //tableView点击响应
        tableView.rx.modelSelected(Music.self).subscribe(onNext: { music in
              print("你选中的歌曲信息【\(music)】")
         }).disposed(by: disposeBag)
    }
}


● DisposeBag:作用是 Rx 在视图控制器或者其持有者将要销毁的时候,自动释法掉绑定在它上面的资源。它是通过类似“订阅处置机制”方式实现(类似于 NotificationCenter 的 removeObserver)。
● rx.items(cellIdentifier:):这是 Rx 基于 cellForRowAt 数据源方法的一个封装。传统方式中我们还要有个 numberOfRowsInSection 方法,使用 Rx 后就不再需要了(Rx 已经帮我们完成了相关工作)。
● rx.modelSelected: 这是 Rx 基于 UITableView委托回调方法 didSelectRowAt 的一个封装。

三、Observable

1.Observable<T>


● Observable<T>是Rx 框架的基础,我们可以称它为可观察序列。它的作用就是可以异步地产生一系列的 Event(事件),即一个 Observable<T> 对象会随着时间推移不定期地发出 event(element : T) 这样一个东西。
● 而且这些 Event 还可以携带数据,它的泛型 <T> 就是用来指定这个Event携带的数据的类型。
● 有了可观察序列,我们还需要有一个Observer(订阅者)来订阅它,这样这个订阅者才能收到 Observable<T> 不时发出的 Event。


2.Event

RxSwift 源码对Event 的定义如下

public enum Event<Element> {
    /// Next element is produced.
    case next(Element)
 
    /// Sequence terminated with an error.
    case error(Swift.Error)
 
    /// Sequence completed successfully.
    case completed
}


next:正常发送携带数据 <T> 的事件
error:发送携带具体的错误内容的事件,observable终止
completed:发送完成事件,observable终止。


3.Observable与Sequence比较


● 一个Observable(ObservableType)相当于一个序列 Sequence(SequenceType)。
● ObservableType.subscribe(_:)方法其实就相当于 SequenceType.generate()
区别:
● Swift 中的 SequenceType 是同步的循环,而 Observable是异步的。
● Observable 对象会在有任何 Event 时候,自动将 Event作为一个参数通过ObservableType.subscribe(_:)发出,并不需要使用 next方法。

4.创建 Observable 序列


(1)just()方法

let observable = Observable<Int>.just(5)
//int指定了这个Observable所发出的事件携带的数据类型必须是 Int 类型的


(2)of() 方法

let observable = Observable.of("A", "B", "C")
//of()方法可以接受可变数量的参数,无显式地声明出 Observable 的泛型类型,Swift也会自动推断类型


(3)from() 方法

let observable = Observable.from(["A", "B", "C"])
//该方法需要一个数组参数,数组里的元素就会被当做这个Observable所发出 event携带的数据内容,最终效果同上面饿 of()样例是一样的


(4)empty() 方法

let observable = Observable<Int>.empty()
//创建一个空内容的Observable序列。


(5)never() 方法

let observable = Observable<Int>.never()
//创建一个永远不会发出 Event(也不会终止)的 Observable 序列


(6)error() 方法

enum MyError: Error {
    case A
    case B
}
         
let observable = Observable<Int>.error(MyError.A)
//创建一个不做任何操作,而是直接发送一个错误的 Observable 序列


(7)range() 方法

//使用range(),创建一个以这个范围内所有值作为初始值的Observable序列。
let observable = Observable.range(start: 1, count: 5)
//相当于使用of()
let observable = Observable.of(1, 2, 3 ,4 ,5)


(8)repeatElement() 方法

let observable = Observable.repeatElement(1)
//创建一个可以无限发出给定元素的 Event的 Observable 序列(永不终止)


(9)generate() 方法

//使用generate()方法,创建一个只有当提供的所有的判断条件都为 true 的时候,才会给出动作的 Observable 序列。
let observable = Observable.generate(
    initialState: 0,
    condition: { $0 <= 10 },
    iterate: { $0 + 2 }
)
 
//相当于使用of()方法
let observable = Observable.of(0 , 2 ,4 ,6 ,8 ,10)


(10)create() 方法

//接受一个 block 形式的参数,任务是对每一个过来的订阅进行处理
//这个block有一个回调参数observer就是订阅这个Observable对象的订阅者
//当一个订阅者订阅这个Observable对象的时候,就会将订阅者作为参数传入这个block来执行一些内容
let observable = Observable<String>.create{ observer in
    //对订阅者发出了.next事件,且携带了一个数据"hangge.com"
    observer.onNext("hangge.com")
    //对订阅者发出了.completed事件
    observer.onCompleted()
    //因为一个订阅行为会有一个Disposable类型的返回值,所以在结尾一定要returen一个Disposable
    return Disposables.create()
}
 
//订阅测试
observable.subscribe {
    print($0)
}


(11)deferred() 方法
该方法相当于是创建一个 Observable 工厂,通过传入一个 block 来执行延迟 Observable序列创建的行为,而这个 block 里就是真正的实例化序列对象的地方。

//用于标记是奇数、还是偶数
var isOdd = true
 
//使用deferred()方法延迟Observable序列的初始化,通过传入的block来实现Observable序列的初始化并且返回。
let factory : Observable<Int> = Observable.deferred {
     
    //让每次执行这个block时候都会让奇、偶数进行交替
    isOdd = !isOdd
     
    //根据isOdd参数,决定创建并返回的是奇数Observable、还是偶数Observable
    if isOdd {
        return Observable.of(1, 3, 5 ,7)
    }else {
        return Observable.of(2, 4, 6, 8)
    }
}
 
//第1次订阅测试
factory.subscribe { event in
    print("\(isOdd)", event)
}
 
//第2次订阅测试
factory.subscribe { event in
    print("\(isOdd)", event)
}


上述例子执行结果

(12)interval() 方法
每隔一段设定的时间,会发出一个索引数的元素。而且它会一直发送下去。

//每1秒发送一次,并且是在主线程(MainScheduler)发送
let observable = Observable<Int>.interval(1, 
                                          scheduler: MainScheduler.instance)
observable.subscribe { event in
    print(event)
}


(13)timer() 方法
两种用法:
一种是创建的 Observable序列在经过设定的一段时间后,产生唯一的一个元素。
另一种是创建的 Observable 序列在经过设定的一段时间后,每隔一段时间产生一个元素。

//5秒种后发出唯一的一个元素0
let observable = Observable<Int>.timer(5, 
                                       scheduler: MainScheduler.instance)
observable.subscribe { event in
    print(event)
}
//延时5秒种后,每隔1秒钟发出一个元素
let observable = Observable<Int>.timer(5, period: 1, 
                                       scheduler: MainScheduler.instance)
observable.subscribe { event in
    print(event)
}


四、订阅 Observable


1.subscribe()订阅.next事件


● 初始化 Observable 序列时设置的默认值都按顺序通过 .next 事件发送出来。
● 当 Observable 序列的初始数据都发送完毕,它还会自动发一个 .completed 事件出来。

let observable = Observable.of("A", "B", "C")
         
observable.subscribe { event in
    //可以通过event.element获取到这个事件里的数据
    print(event.element) 
}



2.subscribe方法通过不同的block回调处理不同类型的event。

let observable = Observable.of("A", "B", "C")
         
observable.subscribe(onNext: { element in
    print(element)
}, onError: { error in
    print(error)
}, onCompleted: {
    print("completed")
}, onDisposed: {
    print("disposed")
})

//onNext、onError、onCompleted 和 onDisposed 这四个回调block参数都是有默认值的,即它们都是可选的。
//可以只处理 onNext而不管其他的情况
let observable = Observable.of("A", "B", "C")
observable.subscribe(onNext: { element in
    print(element)
})

五、监听事件的生命周期

我们可以使用 doOn 方法来监听事件的生命周期,它会在每一次事件发送前被调用。
和 subscribe 一样,可以通过不同的block 回调处理不同类型的 event

let observable = Observable.of("A", "B", "C")
 
observable
    .do(onNext: { element in
        print("Intercepted Next:", element)
    }, onError: { error in
        print("Intercepted Error:", error)
    }, onCompleted: {
        print("Intercepted Completed")
    }, onDispose: {
        print("Intercepted Disposed")
    })
    .subscribe(onNext: { element in
        print(element)
    }, onError: { error in
        print(error)
    }, onCompleted: {
        print("completed")
    }, onDisposed: {
        print("disposed")
    })


六、Observable 的销毁(Dispose)

1.Observable 从创建到终结流程

(1)一个 Observable 序列被创建出来后它不会马上就开始被激活从而发出 Event,而是要等到它被某个人订阅了才会激活它。
(2)而 Observable 序列激活之后要一直等到它发出了.error或者 .completed的 event 后,它才被终结。

2.dispose() 方法

使用该方法我们可以手动取消一个订阅行为。如果我们觉得这个订阅结束了不再需要了,就可以调用 dispose()方法把这个订阅给销毁掉,防止内存泄漏。
当一个订阅行为被dispose 了,那么之后 observable 如果再发出 event,这个已经 dispose 的订阅就收不到消息了

let observable = Observable.of("A", "B", "C")
         
//使用subscription常量存储这个订阅方法
let subscription = observable.subscribe { event in
    print(event)
}
         
//调用这个订阅的dispose()方法
subscription.dispose()

3.DisposeBag


● 我们可以把一个 DisposeBag对象看成一个垃圾袋,把用过的订阅行为都放进去。
● 而这个DisposeBag 就会在自己快要dealloc 的时候,对它里面的所有订阅行为都调用 dispose()方法。

let disposeBag = DisposeBag()
         
//第1个Observable,及其订阅
let observable1 = Observable.of("A", "B", "C")
observable1.subscribe { event in
    print(event)
}.disposed(by: disposeBag)
 
//第2个Observable,及其订阅
let observable2 = Observable.of(1, 2, 3)
observable2.subscribe { event in
    print(event)
}.disposed(by: disposeBag)


七、Observer

观察者(Observer)的作用就是监听事件,然后对这个事件做出响应。或者说,任何响应事件的行为都是观察者。


1.subscribe创建观察者


最直接的方法就是在 Observable 的 subscribe 方法后面描述当事件发生时,需要如何做出响应。

let observable = Observable.of("A", "B", "C")
          
observable.subscribe(onNext: { element in
    print(element)
}, onError: { error in
    print(error)
}, onCompleted: {
    print("completed")
})


2.bind 方法创建观察者

import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    @IBOutlet weak var label: UILabel!
     
    let disposeBag = DisposeBag()
     
    override func viewDidLoad() {
         
        //Observable序列(每隔1秒钟发出一个索引数)
        let observable = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
 
        observable
            .map { "当前索引数:\($0 )"}
            .bind { [weak self](text) in
                //收到发出的索引数后显示到label上
                self?.label.text = text
            }
            .disposed(by: disposeBag)
    }
}

3.AnyObserver创建观察者


(1)配合 subscribe 方法使用

//观察者
let observer: AnyObserver<String> = AnyObserver { (event) in
    switch event {
    case .next(let data):
        print(data)
    case .error(let error):
        print(error)
    case .completed:
        print("completed")
    }
}
 
let observable = Observable.of("A", "B", "C")
observable.subscribe(observer)


(2)配合 bindTo 方法使用

import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    @IBOutlet weak var label: UILabel!
     
    let disposeBag = DisposeBag()
     
    override func viewDidLoad() {
         
        //观察者
        let observer: AnyObserver<String> = AnyObserver { [weak self] (event) in
            switch event {
            case .next(let text):
                //收到发出的索引数后显示到label上
                self?.label.text = text
            default:
                break
            }
        }
         
        //Observable序列(每隔1秒钟发出一个索引数)
        let observable = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
        observable
            .map { "当前索引数:\($0 )"}
            .bind(to: observer)
            .disposed(by: disposeBag)
    }
}

4.Binder 创建观察者


相较于AnyObserver 的大而全,Binder 更专注于特定的场景。
Binder主要有以下两个特征:
● 不会处理错误事件。一旦产生错误事件,在调试环境下将执行 fatalError,在发布环境下将打印错误信息。
● 确保绑定都是在给定 Scheduler 上执行(默认 MainScheduler)

import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    @IBOutlet weak var label: UILabel!
    let disposeBag = DisposeBag()
     
    override func viewDidLoad() {
                 
        //观察者
        let observer: Binder<String> = Binder(label) { (view, text) in
            //收到发出的索引数后显示到label上
            view.text = text
        }
         
        //Observable序列(每隔1秒钟发出一个索引数)
        let observable = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
        observable
            .map { "当前索引数:\($0 )"}
            .bind(to: observer)
            .disposed(by: disposeBag)
    }
}


八、自定义可绑定属性

有时我们想让 UI 控件创建出来后默认就有一些观察者,而不必每次都为它们单独去创建观察者。比如我们想要让所有的 UIlabel 都有个 fontSize 可绑定属性,它会根据事件值自动改变标签的字体大小。
方式一:对 UI 类进行扩展

import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    @IBOutlet weak var label: UILabel!
     
    let disposeBag = DisposeBag()
     
    override func viewDidLoad() {
         
        //Observable序列(每隔0.5秒钟发出一个索引数)
        let observable = Observable<Int>.interval(0.5, scheduler: MainScheduler.instance)
        observable
            .map { CGFloat($0) }
            .bind(to: label.fontSize) //根据索引数不断变放大字体
            .disposed(by: disposeBag)
    }
}
 
extension UILabel {
    public var fontSize: Binder<CGFloat> {
        return Binder(self) { label, fontSize in
            label.font = UIFont.systemFont(ofSize: fontSize)
        }
    }
}


方式二、对 Reactive 类进行扩展
这种方式下,我们绑定属性时要写成 label.rx.fontSize

import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    @IBOutlet weak var label: UILabel!
     
    let disposeBag = DisposeBag()
     
    override func viewDidLoad() {
         
        //Observable序列(每隔0.5秒钟发出一个索引数)
        let observable = Observable<Int>.interval(0.5, scheduler: MainScheduler.instance)
        observable
            .map { CGFloat($0) }
            .bind(to: label.rx.fontSize) //根据索引数不断变放大字体
            .disposed(by: disposeBag)
    }
}
 
extension Reactive where Base: UILabel {
    public var fontSize: Binder<CGFloat> {
        return Binder(self.base) { label, fontSize in
            label.font = UIFont.systemFont(ofSize: fontSize)
        }
    }
}

九、RxSwift 自带的可绑定属性(UI 观察者)

其实 RxSwift 已经为我们提供许多常用的可绑定属性。比如 UILabel 就有 text 和 attributedText 这两个可绑定属性。

import RxSwift
import UIKit
 
extension Reactive where Base: UILabel {
     
    /// Bindable sink for `text` property.
    public var text: Binder<String?> {
        return Binder(self.base) { label, text in
            label.text = text
        }
    }
 
    /// Bindable sink for `attributedText` property.
    public var attributedText: Binder<NSAttributedString?> {
        return Binder(self.base) { label, text in
            label.attributedText = text
        }
    }
     
}


我们其实不需要自定义 UI 观察者,直接使用 RxSwift 提供的绑定属性即可。

import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    @IBOutlet weak var label: UILabel!
     
    let disposeBag = DisposeBag()
     
    override func viewDidLoad() {
         
        //Observable序列(每隔1秒钟发出一个索引数)
        let observable = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
        observable
            .map { "当前索引数:\($0 )"}
            .bind(to: label.rx.text) //收到发出的索引数后显示到label上
            .disposed(by: disposeBag)
    }
}

十、Subjects

Subjects 既是订阅者,也是 Observable
有四种 Subjects,分别为:PublishSubject、BehaviorSubject、ReplaySubject、Variable。他们之间既有各自的特点,也有相同之处:
● 首先他们都是 Observable,他们的订阅者都能收到他们发出的新的 Event。
● 直到 Subject 发出 .complete 或者 .error 的 Event 后,该 Subject 便终结了,同时它也就不会再发出.next事件。
● 对于那些在 Subject 终结后再订阅他的订阅者,也能收到 subject发出的一条 .complete 或 .error的 event,告诉这个新的订阅者它已经终结了。
● 他们之间最大的区别只是在于:当一个新的订阅者刚订阅它的时候,能不能收到 Subject 以前发出过的旧 Event,如果能的话又能收到多少个
Subject 常用的几个方法:
● onNext(:):是 on(.next(:)) 的简便写法。该方法相当于 subject 接收到一个.next 事件。
● onError(:):是 on(.error(:)) 的简便写法。该方法相当于 subject 接收到一个 .error 事件。
● onCompleted():是 on(.completed)的简便写法。该方法相当于 subject 接收到一个 .completed 事件。


1.PublishSubject


● PublishSubject是最普通的 Subject,它不需要初始值就能创建。
● PublishSubject 的订阅者从他们开始订阅的时间点起,可以收到订阅后 Subject 发出的新 Event,而不会收到他们在订阅前已发出的 Event。

let disposeBag = DisposeBag()
 
//创建一个PublishSubject
let subject = PublishSubject<String>()
 
//由于当前没有任何订阅者,所以这条信息不会输出到控制台
subject.onNext("111")
 
//第1次订阅subject
subject.subscribe(onNext: { string in
    print("第1次订阅:", string)
}, onCompleted:{
    print("第1次订阅:onCompleted")
}).disposed(by: disposeBag)
 
//当前有1个订阅,则该信息会输出到控制台
subject.onNext("222")
 
//第2次订阅subject
subject.subscribe(onNext: { string in
    print("第2次订阅:", string)
}, onCompleted:{
    print("第2次订阅:onCompleted")
}).disposed(by: disposeBag)
 
//当前有2个订阅,则该信息会输出到控制台
subject.onNext("333")
 
//让subject结束
subject.onCompleted()
 
//subject完成后会发出.next事件了。
subject.onNext("444")
 
//subject完成后它的所有订阅(包括结束后的订阅),都能收到subject的.completed事件,
subject.subscribe(onNext: { string in
    print("第3次订阅:", string)
}, onCompleted:{
    print("第3次订阅:onCompleted")
}).disposed(by: disposeBag)

2.BehaviorSubject


● BehaviorSubject 需要通过一个默认初始值来创建。
● 当一个订阅者来订阅它的时候,这个订阅者会立即收到 BehaviorSubjects 上一个发出的event。之后就跟正常的情况一样,它也会接收到 BehaviorSubject 之后发出的新的 event。

let disposeBag = DisposeBag()
 
//创建一个BehaviorSubject
let subject = BehaviorSubject(value: "111")
 
//第1次订阅subject
subject.subscribe { event in
    print("第1次订阅:", event)
}.disposed(by: disposeBag)
 
//发送next事件
subject.onNext("222")
 
//发送error事件
subject.onError(NSError(domain: "local", code: 0, userInfo: nil))
 
//第2次订阅subject
subject.subscribe { event in
    print("第2次订阅:", event)
}.disposed(by: disposeBag)

3.ReplaySubject


● ReplaySubject 在创建时候需要设置一个 bufferSize,表示它对于它发送过的 event 的缓存个数。
● 比如一个 ReplaySubject 的 bufferSize 设置为 2,它发出了 3 个 .next 的 event,那么它会将后两个(最近的两个)event 给缓存起来。此时如果有一个 subscriber 订阅了这个 ReplaySubject,那么这个 subscriber 就会立即收到前面缓存的两个.next 的 event。
● 如果一个 subscriber 订阅已经结束的 ReplaySubject,除了会收到缓存的 .next 的 event外,还会收到那个终结的 .error 或者 .complete 的event。

let disposeBag = DisposeBag()
 
//创建一个bufferSize为2的ReplaySubject
let subject = ReplaySubject<String>.create(bufferSize: 2)
 
//连续发送3个next事件
subject.onNext("111")
subject.onNext("222")
subject.onNext("333")
 
//第1次订阅subject
subject.subscribe { event in
    print("第1次订阅:", event)
}.disposed(by: disposeBag)
 
//再发送1个next事件
subject.onNext("444")
 
//第2次订阅subject
subject.subscribe { event in
    print("第2次订阅:", event)
}.disposed(by: disposeBag)
 
//让subject结束
subject.onCompleted()
 
//第3次订阅subject
subject.subscribe { event in
    print("第3次订阅:", event)
}.disposed(by: disposeBag)



4.Variable


● Variable 其实就是对 BehaviorSubject 的封装,所以它也必须要通过一个默认的初始值进行创建。
● Variable 具有 BehaviorSubject 的功能,能够向它的订阅者发出上一个 event 以及之后新创建的 event。
● 不同的是,Variable 还会把当前发出的值保存为自己的状态。同时它会在销毁时自动发送 .complete的 event,不需要也不能手动给 Variables 发送 completed或者 error 事件来结束它。
● 简单地说就是 Variable 有一个 value 属性,我们改变这个 value 属性的值就相当于调用一般 Subjects 的 onNext() 方法,而这个最新的 onNext() 的值就被保存在 value 属性里了,直到我们再次修改它。
Variables 本身没有 subscribe() 方法,但是所有 Subjects 都有一个 asObservable() 方法。我们可以使用这个方法返回这个 Variable 的 Observable 类型,拿到这个 Observable 类型我们就能订阅它了。

import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    override func viewDidLoad() {
        super.viewDidLoad()
 
        let disposeBag = DisposeBag()
         
        //创建一个初始值为111的Variable
        let variable = Variable("111")
         
        //修改value值
        variable.value = "222"
         
        //第1次订阅
        variable.asObservable().subscribe {
            print("第1次订阅:", $0)
        }.disposed(by: disposeBag)
         
        //修改value值
        variable.value = "333"
         
        //第2次订阅
        variable.asObservable().subscribe {
            print("第2次订阅:", $0)
        }.disposed(by: disposeBag)
         
        //修改value值
        variable.value = "444"
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KWMax

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值