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