RxSwift4.0Driver的使用

2020-01-31  本文已影响0人  数字d

Driver提供一种简便的方法在UI层编写响应式代码,简单来说就是序列驱动应用程序,如果序列满足如下特征,就可以使用Driver
1.不会产生error事件
2.一定在主线程监听MainScheduler
3.共享状态变化shareReplayLatestWhileConnected

使用Driver的场景:
1.通过CoreData来驱动UI
2.使用一个UI元素的值(绑定)来驱动另一个UI元素的值
3.与普通的操作系统驱动程序一样,如果出现序列错误,应用程序将停止响应用户输入
4.在主线程上观察到这些元素也是必要的,因为UI元素和应用程序逻辑通常不是线程安全的
5.此外,使用构建Driver的可观察序列,它是共享状态变化

Demo功能是,当TextField输入数据时候(一个UI元素),Lab(另一个UI元素)的text和Btn(另一个UI元素)的Tittle内容发生更改.

这里解释下最基本的实现方法,dealWithData方法先将UitextField的输入的值映射成序列,通过创建序列result,然后对序列result进行订阅,在订阅到序列的逻辑中刷新UI.

dealWithData方法,将字符串转化为序列

    func dealWithData(inputText:String) -> Observable<Any> {

//这里的请求网络是模拟的,并没有真的请求,只是将数据的textField的内容做了更改,实际开发中可以自行修改
        print("请求网络\(Thread.current)")
        
        return Observable<Any>.create { (ob) -> Disposable in
            if inputText == "1234" {
                ob.onError(NSError.init(domain: "log.error", code: 10096, userInfo: nil))
            }
            
            DispatchQueue.global().async {
                print("发送之前的内容:\(Thread.current)")
                ob.onNext("已经输入:\(inputText)")
                ob.onCompleted()
//               子线程刷新UI会crash
//                self.btn.setTitle("123", for: .normal)
            }
            return Disposables.create()
        }
    }

在viewDidLoad中来实现序列的映射

       let result = tf.rx.text.skip(1)
           .flatMap{[weak self](input) -> Observable<Any> in
                return (self?.dealWithData(inputText:input ?? ""))!
  }

在viewDidLoad中实现订阅

       result.subscribe(onNext:{ (element) in
            print("订阅到\(element)")
        })
        result.subscribe(onNext:{ (element) in
            print("订阅到:\(Thread.current) --- \(element)")
        })

以上代码即可实现所需的功能,但是是存在问题的。
问题1:被订阅的次数是多少,网络请求的次数就有多少,这里浪费网络请求资源和带宽
问题2.订阅到的实现是在子线程中的,如果再订阅到的时候刷新UI,代码会crash
问题3.关于自定义的错误回调,也要进行处理。即可以显示错误,但是不能让应用因错误而崩溃。

解决方案:
调用函数

.share(replay: 1, scope: .whileConnected)

这样写网络请求就只执行一次

.observeOn(MainScheduler.instance) 

这样写订阅到的时候就是主线程

接下来是错误事件的处理,这样处理就会将错误处理发出来,而不是直接闪退,减少因为error而出现的闪退

 .catchErrorJustReturn("检测到了error事件")

序列创建综合实现

        let result = tf.rx.text.skip(1)
            .flatMap{[weak self](input) -> Observable<Any> in
                return (self?.dealWithData(inputText:input ?? ""))!
                    .observeOn(MainScheduler.instance)
                .catchErrorJustReturn("检测到了error事件")
        }.share(replay: 1, scope: .whileConnected)

按照上面综合实现的代码可以解决上面提到的三个问题。功能的实现到此结束。

接下来是优化写法方案:

序列的创建方案实现,将oberverable序列转化成driver类型来实现序列的创建

//可选项orEmpty
        let result = tf.rx.text.orEmpty
            .asDriver()
            .flatMap {
                return self.dealWithData(inputText: $0)
                .asDriver(onErrorJustReturn: "检测到错误事件")
                
        }

序列订阅和UI绑定

        result.map{"长度\(($0 as! String).count)"}
            .drive(self.lab.rx.text)
        result.map{"长度\($0 as! String)"}
            .drive(self.btn.rx.title())

按照driver序列的实现

代码拉取地址:

https://gitee.com/xgkp/hFunction.git

实现

图示UI

1
上一篇下一篇

猜你喜欢

热点阅读