zoukankan      html  css  js  c++  java
  • ControlEvent

    ControlEvent

    ControlEvent 专门用于描述 UI 控件所产生的事件,它具有以下特征:

    • 不会产生 error 事件
    • 一定在 MainScheduler 订阅(主线程订阅)
    • 一定在 MainScheduler 监听(主线程监听)
    • 共享附加作用

    Observer - 观察者

    观察者 是用来监听事件,然后它需要对这个事件做出响应。例如:弹出提示框就是观察者,它对点击按钮这个事件做出响应。

    • 响应事件的都是观察者

    image

    • 如何创建观察者

    和 Observable 一样,框架已经帮我们创建好了许多常用的观察者。例如:view 是否隐藏,button 是否可点击, label 的当前文本,imageView 的当前图片等等。

    另外,有一些自定义的观察者是需要我们自己创建的

    tap.subscribe(onNext: { [weak self] in
        self?.showAlert()
    }, onError: { error in
        print("发生错误: (error.localizedDescription)")
    }, onCompleted: {
        print("任务完成")
    })

    创建观察者最直接的方法就是在 Observable 的 subscribe 方法后面描述,事件发生时,需要如何做出响应。而观察者就是由后面的 onNext,onError,onCompleted的这些闭包构建出来的。

    以上是创建观察者最常见的方法。当然还可以通过其他的方式来创建观察者

    AnyObserver

    AnyObserver 可以用来描叙任意一种观察者。

    打印网络请求结果:

    URLSession.shared.rx.data(request: URLRequest(url: url))
        .subscribe(onNext: { data in
            print("Data Task Success with count: (data.count)")
        }, onError: { error in
            print("Data Task Error: (error)")
        })
        .disposed(by: disposeBag)
    

    可以看作是:

    let observer: AnyObserver<Data> = AnyObserver { (event) in
        switch event {
        case .next(let data):
            print("Data Task Success with count: (data.count)")
        case .error(let error):
            print("Data Task Error: (error)")
        default:
            break
        }
    }
    
    URLSession.shared.rx.data(request: URLRequest(url: url))
        .subscribe(observer)
        .disposed(by: disposeBag)
    

    用户名提示语是否隐藏:

    usernameValid
        .bind(to: usernameValidOutlet.rx.isHidden)
        .disposed(by: disposeBag)
    可以看作是:
    
    let observer: AnyObserver<Bool> = AnyObserver { [weak self] (event) in
        switch event {
        case .next(let isHidden):
            self?.usernameValidOutlet.isHidden = isHidden
        default:
            break
        }
    }
    
    usernameValid
        .bind(to: observer)
        .disposed(by: disposeBag)
    

    Binder 特征观察者

    Binder 主要有以下两个特征:

    • 不会处理错误事件
    • 确保绑定都是在给定 Scheduler 上执行(默认 MainScheduler)

    一旦产生错误事件,在调试环境下将执行 fatalError,在发布环境下将打印错误信息。

    let observer: AnyObserver<Bool> = AnyObserver { [weak self] (event) in
        switch event {
        case .next(let isHidden):
            self?.usernameValidOutlet.isHidden = isHidden
        default:
            break
        }
    }
    
    usernameValid
        .bind(to: observer)
        .disposed(by: disposeBag)
    

    由于这个观察者是一个 UI 观察者,所以它在响应事件时,只会处理 next 事件,并且更新 UI 的操作需要在主线程上执行。

    因此一个更好的方案就是使用 Binder:

    let observer: Binder<Bool> = Binder(usernameValidOutlet) { (view, isHidden) in
        view.isHidden = isHidden
    }
    
    usernameValid
        .bind(to: observer)
        .disposed(by: disposeBag)
    

    Binder 可以只处理 next 事件,并且保证响应 next 事件的代码一定会在给定 Scheduler 上执行,这里采用默认的 MainScheduler。

    • 复用

    由于页面是否隐藏是一个常用的观察者,所以应该让所有的 UIView 都提供这种观察者:

    extension Reactive where Base: UIView {
      public var isHidden: Binder<Bool> {
          return Binder(self.base) { view, hidden in
              view.isHidden = hidden
          }
      }
    }
    usernameValid
        .bind(to: usernameValidOutlet.rx.isHidden)
        .disposed(by: disposeBag)
    

    这样你不必为每个 UI 控件单独创建该观察者。这就是 usernameValidOutlet.rx.isHidden 的由来,许多 UI 观察者 都是这样创建的:

    按钮是否可点击 button.rx.isEnabled:

    extension Reactive where Base: UIControl {
      public var isEnabled: Binder<Bool> {
          return Binder(self.base) { control, value in
              control.isEnabled = value
          }
      }
    }

    label 的当前文本 label.rx.text:

    extension Reactive where Base: UILabel {
      public var text: Binder<String?> {
          return Binder(self.base) { label, text in
              label.text = text
          }
      }
    }

    你也可以用这种方式来创建自定义的 UI 观察者。

  • 相关阅读:
    Java之序列化和反序列化
    Java之流的分类
    Java之扫描目录,修改文件内容
    Java之数据流-复制二进制文件
    Java之字符流操作-复制文件
    Java之字节流操作-复制文件
    SQL语句优化原则
    php程序效率优化的一些策略小结
    MYSQL的索引类型:PRIMARY, INDEX,UNIQUE,FULLTEXT,SPAIAL 有什么区别?各适用于什么场合?
    笔记:php有那几种错误提示和查错方法
  • 原文地址:https://www.cnblogs.com/liuxiaokun/p/12682410.html
Copyright © 2011-2022 走看看