特征序列:Single、Completable、Maybe、Dr
2018-09-06 本文已影响20人
FallPine
我们可以将这些特征序列(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) }
- SingleEvent
//获取豆瓣某频道下的歌曲信息
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 }
- CompletableEvent
//将数据缓存到本地
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 }
- MaybeEvent
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)