美文网首页
特征序列:Single、Completable、Maybe、Dr

特征序列:Single、Completable、Maybe、Dr

作者: FallPine | 来源:发表于2018-09-06 14:18 被阅读20次

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

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

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

    • Single

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

      • SingleEvent
        RxSwift 还为 Single 订阅提供了一个枚举(SingleEvent):
        success:里面包含该 Single 的一个元素值
        error:用于包含错误
        public enum SingleEvent<Element> {
           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<Element> {
            case success(Element)
            case error(Swift.Error)
            case completed
        }
        
    func generateString() -> Maybe<String> {
        return Maybe<String>.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<String?>:

    extension Reactive where Base: UITextField {
     
        public var text: ControlProperty<String?> {
            return value
        }
     
        public var value: ControlProperty<String?> {
            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<Void>:

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

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

    相关文章

      网友评论

          本文标题:特征序列:Single、Completable、Maybe、Dr

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