Rx Swifit

作者: f8d1cf28626a | 来源:发表于2024-06-29 15:03 被阅读0次

Rx Swift

RxSwift 是 ReactiveX 成员之一,简单粗暴的理解一下RxSwift.

  • Event 事件

  • Observable 发布者

  • Subscribe 订阅

  • Observer 观察者

我们通过下面代码方便理解

  • 单个事件

// 单个事件Observable:该Observable只能发出一个next事件 + 一个completed事件
//
// 1、调用Observable的类方法just就可以快捷创建一个单个事件observable,可以省略泛型,直接传你想发送的数据就行,会自动给你泛好
// 2、创建好、被监听后,该Observable就会自动发出事件
let justObservable = Observable.just(1)

// 等价于
let observable = Observable<Int>.create { observer in
    observer.onNext(1)
    observer.onCompleted()
    return Disposables.create()
}

  • 多个事件

// 多个事件Observable:该Observable能发出多个next事件 + 一个completed事件
//
// 1、调用Observable的类方法from或of就可以快捷创建一个多个事件observable,可以省略泛型,直接传你想发送的数据就行,会自动给你泛好
// 2、创建好、被监听后,该Observable就会自动发出事件
let fromObservable = Observable.from([1, 2, 3]) // 通过数组来生成多个next事件
let ofObservable = Observable.of(1, 2, 3) // 通过可变参数来生成多个next事件

// 等价于
let observable = Observable<Int>.create { observer in
    observer.onNext(1)
    observer.onNext(2)
    observer.onNext(3)
    observer.onCompleted()
    return Disposables.create()
}

  • 重复事件

// 重复N次Observable:给定一个重复次数N,该Observable就会重复发出同一个next事件N次 + 一个completed事件
let repeatElementObservable = Observable.repeatElement(1)
repeatElementObservable.take(5)

  • 定时器 timer

// 定时器Observable:完全就是一个定时器,必须泛整型。延迟多长时间、每隔多长时间、在哪个线程,该Observable会像个定时器一样不断发出累加的整数
//
// 如果想取消定时器,其实不用取消定时器Observable,你只需要把监听行为给释放掉就可以了,这样的话定时器Observable还是存在的,它并不会发出completed事件或error事件
let timerObservable = Observable<Int>.timer(.seconds(3), period: .seconds(1), scheduler: MainScheduler.instance)

  • Observer有两种类型:(它们都是一个泛型结构体 ObserverType )

    • AnyObserver(任意属性的观察者)

    • Binder(一般都是UI控件属性的观察者)


// 注意:类型为ObserverType
public struct AnyObserver<Element> : ObserverType {
    ...
}

// 注意:类型为ObserverType
public struct Binder<Element>: ObserverType {
    ...
}

需要注意的是Observer想要监听的数据的数据类型就是泛型的这个Element,如果它跟Observable和Event那里的泛型Element不一样,我们就得先通过map等函数把数据类型给搞一样。

  • AnyObserver做相应的处理

// 1、怎么创建一个anyObeserver?
//
// 调用AnyObserver的init方法就可以创建一个anyObserver,假设这个anyObserver想要监听的数据的数据类型为Int
//
// init方法的入参是一个闭包,这个闭包的入参是一个event——这个event就是将来被观察的Observable所发出的事件,这个闭包的执行体就是AnyObserver要做的处理
let anyObserver = AnyObserver<Int>.init { event in
    // 2、anyObserver怎么做出相应的处理?
    // 在这个闭包的执行体里做相应的处理即可
    switch event {
    case .next:
        print("next:\(event.element)")
    case .error:
        print("error:\(event.error)")
    case .completed:
        print("completed")
    }
}

  • Binder做相应的处理

// 1、怎么创建一个Binder?
//
// 调用Binder的init方法就可以创建一个binder,假设这个binder想要监听的数据的数据类型为String(假设我们想监听字符串数据,把监听到的字符串数据设置到一个label上显示)
//
// init方法的第一个入参是指你要把监听到的数据设置给谁来使用,通常是一个UI控件
// init方法的第二个入参是一个闭包,这个闭包的第一个入参就是前面的那个UI控件,第二个入参就是监听到的字符串数据,这个闭包的执行体就是binder要做的处理
let binder = Binder<String>.init(label) { label, element in
    // 2、binder怎么做出相应的处理?
    // 在这个闭包的执行体里做相应的处理即可
    label.text = element
}

Observer监听Observable,以及监听行为的释放

  • Observable Subscribe AnyObserver

let timerObservable = Observable<Int>.timer(.seconds(3), period: .seconds(1), scheduler: MainScheduler.instance)

let anyObserver = AnyObserver<Int>.init { event in
    switch event {
    case .next:
        print("next:\(event.element)")  // 会打印:0、1、2、3、...
    case .error:
        print("error:\(event.error)")
    case .completed:
        print("completed")
    }
}


timerObservable.subscribe(anyObserver)

  • Observable Subscribe Binder

// 界面上搞一个label
@IBOutlet weak var label: UILabel!

let timerObservable = Observable<Int>.timer(.seconds(3), period: .seconds(1), scheduler: MainScheduler.instance)
let binder = Binder<String>.init(label) { label, element in
    label.text = element
}

// binder监听timerObservable
// 但是timerObservable发出的事件挂的数据是Int类型
// 而binder监听的确实String类型
// 所以得把timerObservable发出的事件挂的Int数据通过map函数转换成String数据
// 就这么简单
timerObservable
    .map { element in
        return "数字是:\(element)"
    }
    .subscribe(binder)

// Binder还有一个专门的bindTo方法用来监听Observable,不过跟subscribe方法是等价的
timerObservable
    .map { element in
        return "数字是:\(element)"
    }
    .bind(to: binder)

  • 广义上的观察者

let timerObservable = Observable<Int>.timer(.seconds(3), period: .seconds(1), scheduler: MainScheduler.instance)

// 方式1
timerObservable
    .subscribe { event in
        switch event {
        case .next:
            print("next:\(event.element)")  // 会打印:0、1、2、3、...
        case .error:
            print("error:\(event.error)")
        case .completed:
            print("completed")
        }
    }

// 方式2
timerObservable
    .subscribe(onNext: { element in
        print("next:\(element)")  // 会打印:0、1、2、3、...
    }, onError: { error in
        print("error:\(error)")
    }, onCompleted: {
        print("completed")
    })

subscribe 函数有一个返回值 Disposable

  • disposable 立即释放监听行为(实际开发中使用较少)

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let timerObservable = Observable<Int>.timer(.seconds(3), period: .seconds(1), scheduler: MainScheduler.instance)
        let anyObserver = AnyObserver<Int>.init { event in
            switch event {
            case .next:
                print("next:\(event.element)")
            case .error:
                print("error:\(event.error)")
            case .completed:
                print("completed")
            }
        }

        let disposable = timerObservable.subscribe(anyObserver)
        // 立即释放监听行为——即接收完释放之前的一波数据后立即释放,类似于release
        disposable.dispose()
    }
}

  • disposable 自动释放监听行为(实际开发中使用较多)

class ViewController: UIViewController {
    // 类似于autoreleasepool
    //
    // 它会把所有的监听行为都放进去,等到它即将销毁时再对它里面所有的监听行为都调用一次dispose方法
    // 现在bag属性的生命周期是跟当前viewController一样的
    let bag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let timerObservable = Observable<Int>.timer(.seconds(3), period: .seconds(1), scheduler: MainScheduler.instance)
        let anyObserver = AnyObserver<Int>.init { event in
            switch event {
            case .next:
                print("next:\(event.element)")
            case .error:
                print("error:\(event.error)")
            case .completed:
                print("completed")
            }
        }
        
        timerObservable.subscribe(anyObserver).disposed(by: bag)
    }
}

  • 用手 释放监听行为

class ViewController: UIViewController {
    // 定义一个属性
    var disposable: Disposable?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let timerObservable = Observable<Int>.timer(.seconds(3), period: .seconds(1), scheduler: MainScheduler.instance)
        let anyObserver = AnyObserver<Int>.init { event in
            switch event {
            case .next:
                print("next:\(event.element)")
            case .error:
                print("error:\(event.error)")
            case .completed:
                print("completed")
            }
        }
        
        // 把监听行为记录下来
        disposable = timerObservable.subscribe(anyObserver)
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        // 在合适的时机手动释放监听行为
        disposable?.dispose()
    }
}

Subjects

  • PublishSubject

    • publishSubject在充当Observable发出事件,也能充当Observer

class ViewController: UIViewController {
    let bag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let publishSubject = PublishSubject<Int>.init()
        
        // 这里publishSubject在充当Observer的角色,帮Observable发出事件
        // 还记得之前创建Observable时,Observable是怎么发出事件的吗?就是给Observer发送onNext消息发出的,onNext本来就是Observer的方法,所以这里就体现了publishSubject在充当Observer的角色
        publishSubject.onNext(1)
        publishSubject.onNext(2)
        publishSubject.onNext(3)
        
        // 这里publishSubject在充当Observable的角色,只会向观察者发送观察者监听它之后的事件,不会向观察者发送观察者监听它之前的事件
        publishSubject.subscribe { event in
            print(event) // 4、5、6
        }.disposed(by: bag)
        
        
        publishSubject.onNext(4)
        publishSubject.onNext(5)
        publishSubject.onNext(6)
    }
}

  • BehaviorSubject

    • behaviorSubject在充当Observable发出事件,也能充当Observer

class ViewController: UIViewController {
    let bag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

        let behaviorSubject = BehaviorSubject<Int>(value: 1)

        // 这里behaviorSubject在充当Observer的角色,帮Observable发出事件
        behaviorSubject.onNext(2)
        behaviorSubject.onNext(3)

        // 这里behaviorSubject在充当Observable的角色,会向观察者发送观察者监听它之前的最后一个事件 + 观察者监听它之后的事件
        behaviorSubject.subscribe { event in
            print(event) // 3、4、5、6
        }.disposed(by: bag)

        behaviorSubject.onNext(4)
        behaviorSubject.onNext(5)
        behaviorSubject.onNext(6)
    }
}

  • ReplaySubject

    • replaySubject在充当Observable发出事件,也能充当Observer, 可控制缓存数量

class ViewController: UIViewController {
    let bag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let replaySubject = ReplaySubject<Int>.create(bufferSize: 2) // 假设要缓存两个事件
        
        // 这里replaySubject在充当Observer的角色,帮Observable发出事件
        replaySubject.onNext(1)
        replaySubject.onNext(2)
        replaySubject.onNext(3)
        
        // 这里replaySubject在充当Observable的角色,会向观察者发送观察者监听它之前缓存的N个事件 + 观察者监听它之后的事件
        replaySubject.subscribe { event in
            print(event) // 2、3、4、5、6。缓存的是最后两个事件,因为是序列,所以会按顺序把事件发出来
        }.disposed(by: bag)
        
        replaySubject.onNext(4)
        replaySubject.onNext(5)
        replaySubject.onNext(6)
    }
}

  • BehaviorRelay

    • behaviorRelay在充当Observable发出事件,也能充当Observer

class ViewController: UIViewController {
    let bag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let behaviorRelay = BehaviorRelay<Int>.init(value: 1)
        
        // 这里behaviorRelay在充当Observer的角色,帮Observable发出事件
        behaviorRelay.accept(2)
        behaviorRelay.accept(3)
        
        // 这里behaviorRelay在充当Observable的角色,会向观察者发送观察者监听它之前的最后一个事件 + 观察者监听它之后的事件
        behaviorRelay.subscribe { event in
            print(event) // 3、4、5、6
        }.disposed(by: bag)
        
        behaviorRelay.accept(4)
        behaviorRelay.accept(5)
        behaviorRelay.accept(6)
    }
}

实际开发中的用法示例

  • button点击事件

//MARK: - RxSwift应用-button响应
func setupButton() {
    // 传统UI事件
    self.button.addTarget(self, action: #selector(didClickButton), for: .touchUpInside)
    
    // 这样的操作 - 不行啊!代码逻辑与事件逻辑分层
    self.button.rx.tap
        .subscribe(onNext: { [weak self] in
            print("点了,你的小鸡鸡")
            self?.view.backgroundColor = UIColor.orange   
        })
        .disposed(by: disposeBag) 
}

  • textfiled文本响应

//MARK: - RxSwift应用-textfiled
func setupTextFiled() {
    // 我们如果要对输入的文本进行操作 - 比如输入的的内容 然后我们获取里面的偶数
    // self.textFiled.delegate = self
    // 感觉是不是特别恶心
    // 下面我们来看看Rx
    self.textFiled.rx.text.orEmpty.changed.subscribe(onNext: { (text) in
        print("监听到了 - \(text)")
    }).disposed(by: disposeBag)
    
    self.textFiled.rx.text.bind(to: self.button.rx.title()).disposed(by: disposeBag)
}

  • scrollView效果

//MARK: - RxSwift应用-scrollView
func setupScrollerView() {
    scrollView.rx.contentOffset.subscribe(onNext: { [weak self] (content) in
        self?.view.backgroundColor = UIColor.init(red: content.y/255.0*0.8, green: content.y/255.0*0.3, blue: content.y/255.0*0.6, alpha: 1);
        print(content.y)
    }).disposed(by: disposeBag)
}

  • KVO

 //MARK: - RxSwift应用-KVO
func setupKVO() {
    // 系统KVO 还是比较麻烦的
    // person.addObserver(self, forKeyPath: "name", options: .new, context: nil)
    person.rx.observeWeakly(String.self, "name").subscribe(onNext: { (change) in
        print(change ?? "helloword")
    }).disposed(by: disposeBag)
}

  • notification

//MARK: - 通知
func setupNotification(){
    NotificationCenter.default.rx
        .notification(UIResponder.keyboardWillShowNotification)
        .subscribe { (event) in
            print(event)
    }.disposed(by: disposeBag)
}

  • gesture

//MARK: - 手势
func setupGestureRecognizer(){
    let tap = UITapGestureRecognizer()
    self.label.addGestureRecognizer(tap)
    self.label.isUserInteractionEnabled = true
    tap.rx.event.subscribe { (event) in
        print("点了label")
    }.disposed(by: disposeBag)  
}

  • network request

//MARK: - RxSwift应用-网络请求
func setupNextwork() {
    let url = URL(string: "https://www.baidu.com")
    URLSession.shared.rx.response(request: URLRequest(url: url!))
        .subscribe(onNext: { (response, data) in
            print("response ==== \(response)")
            print("data ===== \(data)")
        }, onError: { (error) in
            print("error ===== \(error)")
        }).disposed(by: disposeBag)
}

  • timer

//MARK: - RxSwift应用-timer定时器
func setupTimer() {
    timer = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
    timer.subscribe(onNext: { (num) in
        print("hello word \(num)")
    }).disposed(by: disposeBag)
}

RxSwift实现的timer免去了我们计时器的一些不必要的麻烦
runloop影响
销毁问题
线程问题

666 哈哈哈哈哈哈

相关文章

网友评论

      本文标题:Rx Swifit

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