特征序列:Single、Completable、Maybe、Driver、ControlProperty、ControlEvent

我们可以将这些特征序列(Traits) 看作是 Observable 的另外一个版本。它们之间的区别是:

  • Observable 是能够用于任何上下文环境的通用序列

  • 而 Traits 可以帮助我们更准确的描述序列。同时它们还为我们提供上下文含义、语法糖,让我们能够用更加优雅的方式书写代码

  • Single

    Single它不像 Observable 可以发出多个元素,它要么只能发出一个元素,要么产生一个 error 事件,而且不会共享状态变化
    Single 比较常见的例子就是执行 HTTP 请求,然后返回一个应答或错误,不过我们也可以用 Single 来描述任何只有一个元素的序列

    • SingleEvent
      RxSwift 还为 Single 订阅提供了一个枚举(SingleEvent):
      success:里面包含该 Single 的一个元素值
      error:用于包含错误
      public enum SingleEvent {
         case success(Element)
         case error(Swift.Error)
      }
      
//获取豆瓣某频道下的歌曲信息
    func getPlaylist(_ channel: String) -> Single<[String: Any]> {
        return Single<[String: Any]>.create { single in
            let url = "https://douban.fm/j/mine/playlist?"
                + "type=n&channel=\(channel)&from=mainsite"
            let task = URLSession.shared.dataTask(with: URL(string: url)!) { data, _, error in
                if let error = error {
                    single(.error(error))
                    return
                }
                
                guard let data = data,
                    let json = try? JSONSerialization.jsonObject(with: data,
                                                                 options: .mutableLeaves),
                    let result = json as? [String: Any] else {
                        single(.error(DataError.cantParseJSON))
                        return
                }
                
                single(.success(result))
            }
            
            task.resume()
            
            return Disposables.create { task.cancel() }
        }
    }
  • asSingle()

    我们可以通过调用 Observable 序列的 .asSingle() 方法,将它转换为 Single
Observable.of("1")
    .asSingle()
    .subscribe({ print($0) })
    .disposed(by: disposeBag)
  • Completable

    不会发出任何元素
    只会发出一个 completed 事件或者一个 error 事件
    不会共享状态变化
    适用于那些只关心任务是否完成,而不需要在意任务返回值的情况。比如:在程序退出时将一些数据缓存到本地文件,供下次启动时加载。像这种情况我们只关心缓存是否成功
    • CompletableEvent
      RxSwift 为 Completable 订阅提供了一个枚举(CompletableEvent):
      completed:用于产生完成事件
      error:用于产生一个错误
      public enum CompletableEvent {
          case error(Swift.Error)
          case completed
      }
      
//将数据缓存到本地
    func cacheLocally() -> Completable {
        return Completable.create { completable in
            //将数据缓存到本地(这里掠过具体的业务代码,随机成功或失败)
            let success = (arc4random() % 2 == 0)
            
            guard success else {
                completable(.error(CacheError.failedCaching))
                return Disposables.create {}
            }
            
            completable(.completed)
            return Disposables.create {}
        }
    }
  • Maybe

    它介于 Single 和 Completable 之间,它要么只能发出一个元素,要么产生一个 completed 事件,要么产生一个 error 事件,不会共享状态变化
    • MaybeEvent
      RxSwift 为 Maybe 订阅提供了一个枚举(MaybeEvent):
      success:里包含该 Maybe 的一个元素值
      completed:用于产生完成事件
      error:用于产生一个错误
      public enum MaybeEvent {
          case success(Element)
          case error(Swift.Error)
          case completed
      }
      
func generateString() -> Maybe {
    return Maybe.create { maybe in
         
        //成功并发出一个元素
        maybe(.success("hangge.com"))
         
        //成功但不发出任何元素
        maybe(.completed)
         
        //失败
        //maybe(.error(StringError.failedGenerate))
         
        return Disposables.create {}
    }
}
  • asMaybe()

    我们可以通过调用 Observable 序列的 .asMaybe() 方法,将它转换为 Maybe
Observable.of("1")
    .asMaybe()
    .subscribe({ print($0) })
    .disposed(by: disposeBag)
  • Driver

    Driver 可以说是最复杂的 trait,它的目标是提供一种简便的方式在 UI 层编写响应式代码。
    如果我们的序列满足如下特征,就可以使用它:
    不会产生 error 事件
    一定在主线程监听(MainScheduler)
    共享状态变化(shareReplayLatestWhileConnected)
let results = query.rx.text.asDriver()        // 将普通序列转换为 Driver
    .throttle(0.3, scheduler: MainScheduler.instance)
    .flatMapLatest { query in
        fetchAutoCompleteItems(query)
            .asDriver(onErrorJustReturn: [])  // 仅仅提供发生错误时的备选返回值
    }
 
//将返回的结果绑定到显示结果数量的label上
results
    .map { "\($0.count)" }
    .drive(resultCount.rx.text) // 这里使用 drive 而不是 bindTo
    .disposed(by: disposeBag)
 
//将返回的结果绑定到tableView上
results
    .drive(resultsTableView.rx.items(cellIdentifier: "Cell")) { //  同样使用 drive 而不是 bindTo
        (_, result, cell) in
        cell.textLabel?.text = "\(result)"
    }
    .disposed(by: disposeBag)
  • ControlProperty

    ControlProperty 是专门用来描述 UI 控件属性,拥有该类型的属性都是被观察者(Observable)
    ControlProperty 具有以下特征:
    不会产生 error 事件
    一定在 MainScheduler 订阅(主线程订阅)
    一定在 MainScheduler 监听(主线程监听)
    共享状态变化

其实在 RxCocoa 下许多 UI 控件属性都是被观察者(可观察序列)。比如我们查看源码(UITextField+Rx.swift),可以发现 UITextField 的 rx.text 属性类型便是 ControlProperty

extension Reactive where Base: UITextField {
 
    public var text: ControlProperty {
        return value
    }
 
    public var value: ControlProperty {
        return base.rx.controlPropertyWithDefaultEvents(
            getter: { textField in
                textField.text
        },
            setter: { textField, value in
                if textField.text != value {
                    textField.text = value
                }
        }
        )
    }
     
    //......
}
  • ControlEvent

    ControlEvent 是专门用于描述 UI 所产生的事件,拥有该类型的属性都是被观察者(Observable)。
    ControlEvent 和 ControlProperty 一样,都具有以下特征:
    不会产生 error 事件
    一定在 MainScheduler 订阅(主线程订阅)
    一定在 MainScheduler 监听(主线程监听)
    共享状态变化

同样地,在 RxCocoa 下许多 UI 控件的事件方法都是被观察者(可观察序列)。比如我们查看源码(UIButton+Rx.swift),可以发现 UIButton 的 rx.tap 方法类型便是 ControlEvent

extension Reactive where Base: UIButton {
    public var tap: ControlEvent {
        return controlEvent(.touchUpInside)
    }
}

参考文章:Swift - RxSwift的使用详解17(特征序列1:Single、Completable、Maybe)
Swift - RxSwift的使用详解18(特征序列2:Driver)
Swift - RxSwift的使用详解19(特征序列3:ControlProperty、 ControlEvent)

你可能感兴趣的:(特征序列:Single、Completable、Maybe、Driver、ControlProperty、ControlEvent)