Driver
Driver是RxSwift里的一个高阶函数,一般我们会在发送网络请求时,将请求后的数据drive到我们想要绑定的UI序列中,为什么要使用Driver呢?Driver又是什么呢?我们一起来看下它的底层实现。
请看源码:
let result = inputTF.rx.text.orEmpty
.asDriver()
.flatMap {
return self.dealwithData(inputText: $0)
.asDriver(onErrorJustReturn: "检测到了错误事件")
}
// 请求一次网络
// 绑定到了UI - 主线程
// titlt - 非error
result.map { "长度: \(($0 as! String).count)"}.drive(self.textLabel.rx.text)
result.map { "\($0 as! String)"}
.drive(self.btn.rx.title())
func dealwithData(inputText:String)-> Observable<Any>{
print("请求网络了 \(Thread.current)") // data
return Observable<Any>.create({ (ob) -> Disposable in
if inputText == "1234" {
ob.onError(NSError.init(domain: "com.lgcooci.cn", code: 10086, userInfo: nil))
}// json - model username pasword
// username passopp - lgError - 8001 - httpCoder 100 - 500
// 封装 vm - error -
DispatchQueue.global().async {
print("发送之前看看: \(Thread.current)")
ob.onNext("已经输入:\(inputText)")
ob.onCompleted()
}
return Disposables.create()
})
}
- 我们模拟一个需求,假设当我们在
textField
中输入1个字符就向服务器发送一次请求dealwithData(inputText:String)->Observable<Any>
假设在请求完数据后在异步
通过观察者ob
调用onNext
函数发送给订阅者。
*onErrorJustReturn :
这个方法可以将error错误转化为onNext事件。
*dirve
将响应序列绑定到UI
序列上。
在这里我们就有疑问了,既然是在异步
发送响应,那么我们帮的UI序列时怎么没有在主线程
里做绑定呢?那当然就是Driver
老司机的功劳啦。我们现在开始点进去看看Driver
老司机就近做了什么骚操作。
Driver的初始化
extension ControlProperty {
/// Converts `ControlProperty` to `Driver` trait.
///
/// `ControlProperty` already can't fail, so no special case needs to be handled.
//ControlProperty已经不能失败,所以不需要处理任何特殊情况。
public func asDriver() -> Driver<Element> {
return self.asDriver { _ -> Driver<Element> in
#if DEBUG
rxFatalError("Somehow driver received error from a source that shouldn't fail.")
#else
return Driver.empty()
#endif
}
}
}
-
asDriver()
是ControlProperty
结构体的拓展,他的返回值为self.asDriver的闭包
public typealias Driver<Element> = SharedSequence<DriverSharingStrategy, Element>
- 再点击
Driver
后我们发现他是SharedSequence
的一个别名,我们把它称为共享序列
public struct SharedSequence<SharingStrategy: SharingStrategyProtocol, Element> : SharedSequenceConvertibleType {
let _source: Observable<Element>
init(_ source: Observable<Element>) {
self._source = SharingStrategy.share(source)
}
}
-
Driver
初始化时,_source
属性保存了SharingStrategy.share(source)
产生的可观察序列
public struct DriverSharingStrategy: SharingStrategyProtocol {
public static var scheduler: SchedulerType { return SharingScheduler.make() }
public static func share<Element>(_ source: Observable<Element>) -> Observable<Element> {
return source.share(replay: 1, scope: .whileConnected)
}
}
public enum SharingScheduler {
/// Default scheduler used in SharedSequence based traits.
public private(set) static var make: () -> SchedulerType = { MainScheduler() }
}
public final class MainScheduler : SerialDispatchQueueScheduler {
private let _mainQueue: DispatchQueue
/// Initializes new instance of `MainScheduler`.
public init() {
self._mainQueue = DispatchQueue.main
super.init(serialQueue: self._mainQueue)
}
}
/**
- 由上可知
Driver
在初始化的时候,它的子类初始化时将scheduler 调度器
设置在了主队列上
为什么要使用Driver?
(1)Driver
最常使用的场景应该就是需要用序列来驱动应用程序的情况了,比如:
* 通过 CoreData
模型驱动UI
* 使⽤一个UI
元素值(绑定)来驱动另一个UI
元素值
(2)与普通的操作系统驱动程序⼀一样,如果出现序列列错误,应用程序将停⽌响应用户输入。
(3)在主线程上观察到这些元素也是极其重要的,因为UI
元素和应用程序逻辑通常不是线程安全的。
(4)此外,使用构建 Driver
的可观察的序列列,它是共享状态变化。
(5)Driver
可以说是最复杂的trait
,它的目标是提供一种简便的方式在 UI
层编写响应式代码。
(6)如果我们的序列满足如下特征,就可以使用它:
• 不会产生 error 事件
• 一定在主线程监听(MainScheduler)
• 共享状态变化(shareReplayLatestWhileConnected)