美文网首页
RxSwift4.0Driver的使用

RxSwift4.0Driver的使用

作者: 数字d | 来源:发表于2020-01-31 17:40 被阅读0次

    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

    相关文章

      网友评论

          本文标题:RxSwift4.0Driver的使用

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