生活随笔
收集整理的這篇文章主要介紹了
RxSwift之深入解析场景特征序列的使用和底层实现
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
一、引序
任何序列都可以用 Observable 描述,創(chuàng)建序列 -> 訂閱序列 -> 信號發(fā)送 -> 信號接收:
Observable < Any > . create
{ ( observer
) - > Disposable in observer
. onNext ( "信號1" ) return Disposables . create ( ) } . subscribe ( onNext
: { ( val
) in print ( "信號接收區(qū):\( val) " ) } ) . disposed ( by
: disposeBag
)
Observable 是通用序列的描述符,調(diào)用 .onNext,.onError,onCompleted 來發(fā)送信號,通用性強(qiáng),但針對特殊需求可能會覺得繁瑣,因此 RxSwift 還提供了一組特征序列,是 Observable 序列的變種,它能夠更準(zhǔn)確的描述序列,即 Single、Completable、Maybe、Driver、Signal、ControlEvent,binder 等。
二、Single
① Single 的使用
Single 單元素序列,信號只發(fā)送一次,響應(yīng)信號或錯誤信號。 Single 是 Observable 的另外一個版本,不像 Observable 可以發(fā)出多個元素,它要么只能發(fā)出一個元素,要么產(chǎn)生一個 error 事件。 Single 發(fā)出一個元素,或一個 error 事件,不會共享附加作用。
let singleOB
= Single < Any > . create
{ ( single
) - > Disposable in print ( "singleOB 是否共享" ) single ( . success ( "good" ) ) single ( . error ( NSError . init ( domain
: "com.ydw.cn" , code
: 10086 , userInfo
: nil ) ) ) return Disposables . create ( ) } singleOB
. subscribe
{ ( reslut
) in print ( "訂閱:\( reslut) " ) } . disposed ( by
: disposeBag
) singleOB 是否共享訂閱
: success ( "good" )
說明: sinngle(.success(data)) -> onSuccess 發(fā)送響應(yīng)元素到成功觀察者; sinngle(.error(error)) -> error 發(fā)送錯誤元素到錯誤觀察者。 響應(yīng)元素和錯誤元素分開處理,此時可以聯(lián)想到應(yīng)用中的網(wǎng)絡(luò)請求,成功數(shù)據(jù)用來渲染,錯誤數(shù)則據(jù)彈出提示框。
② Single 的源碼分析
Single 定義:定位到 Single.swift 文件,可以看到 Single 是 PrimitiveSequence 結(jié)構(gòu)體類型的別名,SingleEvent 是事件枚舉,有 success 和 error 兩個成員變量,如下所示:
public enum SingleTrait { } public typealias Single < Element > = PrimitiveSequence < SingleTrait , Element > public enum SingleEvent < Element > { case success ( Element ) case error ( Swift . Error ) }
Single 的 create 創(chuàng)建序列(1??),如下所示:
extension PrimitiveSequenceType where TraitType == SingleTrait { public typealias SingleObserver = ( SingleEvent < ElementType > ) - > Void . . . . . . public static func create ( subscribe
: @escaping
( @escaping
SingleObserver ) - > Disposable ) - > Single < ElementType > { let source
= Observable < ElementType > . create
{ observer
in return subscribe
{ event
in switch event
{ case . success ( let element
) : observer
. on ( . next ( element
) ) observer
. on ( . completed
) case . error ( let error
) : observer
. on ( . error ( error
) ) } } } return PrimitiveSequence ( raw
: source
) } }
可以看到參數(shù)是一個帶 Disposable 類型返回值的閉包,交由外部(業(yè)務(wù)層)實(shí)現(xiàn),內(nèi)部調(diào)用向外傳入一個 SingleObserver 閉包,以上寫法不太好理解,可以換一種寫法: 內(nèi)部實(shí)現(xiàn)一個閉包 block,用來接收外界傳入的 SingleEvent 信號,接著做進(jìn)一步的信號發(fā)送; 調(diào)用外部實(shí)現(xiàn)的閉包方法,將內(nèi)部實(shí)現(xiàn)的閉包 block 發(fā)送出去,起連接作用; 創(chuàng)建 PrimitiveSequence 對象并保存 Observable 序列對象 source,返回 PrimitiveSequence 對象;
public static func create ( subscribe
: @escaping
( @escaping
SingleObserver ) - > Disposable ) - > Single < ElementType > { let source
= Observable < ElementType > . create
{ observer
in let block
= { ( event
: SingleEvent < ElementType > ) - > Void in switch event
{ case . success ( let element
) : observer
. on ( . next ( element
) ) observer
. on ( . completed
) case . error ( let error
) : observer
. on ( . error ( error
) ) } } let disposable
= subscribe ( block
) return disposable
} return PrimitiveSequence ( raw
: source
) }
在 create 方法內(nèi)部實(shí)際上實(shí)現(xiàn)了一個 Observable 序列,由此可見 Single 序列是對 Observable 序列的封裝,Disposable 對象通過閉包交由業(yè)務(wù)層創(chuàng)建,Single 序列在實(shí)現(xiàn)上,方式方法與 Observable 保持一致。Observable 序列的信號傳遞流程,請參考我的博客:RxSwift之深入解析核心邏輯Observable的底層原理。 訂閱序列,也是在同 PrimitiveSequenceType 擴(kuò)展中定義(2??),如下:
public func subscribe ( onSuccess
: ( ( ElementType ) - > Void ) ? = nil , onError
: ( ( Swift . Error ) - > Void ) ? = nil ) - > Disposable { #
if DEBUG let callStack
= Hooks . recordCallStackOnError
? Thread . callStackSymbols
: [ ] #
else let callStack
= [ String ] ( ) #endif
return self . primitiveSequence
. subscribe
{ event
in switch event
{ case . success ( let element
) : onSuccess
? ( element
) case . error ( let error
) : if let onError
= onError
{ onError ( error
) } else { Hooks . defaultErrorHandler ( callStack
, error
) } } } }
方法中先調(diào)用了 self.primitiveSequence 方法,返回了 self,方法是在遵循 PrimitiveSequenceType 協(xié)議的 PrimitiveSequence 的擴(kuò)展中,為了保證協(xié)議的一致性,如下所示:
extension PrimitiveSequence : PrimitiveSequenceType { public typealias TraitType = Trait public typealias ElementType = Element public var primitiveSequence
: PrimitiveSequence < TraitType , ElementType > { return self } }
接著調(diào)用另一個 subscribe 方法(3??),self.primitiveSequence -> asObservable() -> subscribe,此處截斷了 completed 信號的向上傳遞,因此 Single 序列只能收到響應(yīng)信號和錯誤信號,如下:
public func subscribe ( _ observer
: @escaping
( SingleEvent < ElementType > ) - > Void ) - > Disposable { var stopped
= false return self . primitiveSequence
. asObservable ( ) . subscribe
{ event
in if stopped
{ return } stopped
= true switch event
{ case . next ( let element
) : observer ( . success ( element
) ) case . error ( let error
) : observer ( . error ( error
) ) case . completed
: rxFatalErrorInDebug ( "Singles can't emit a completion event" ) } } }
subscribe 方法也調(diào)用了 self.primitiveSequence 方法,接著調(diào)用 asObservable() 方法,查看代碼發(fā)現(xiàn)此處是為了獲取 source 對象,即 Observable 可觀察序列。再查看 subscribe 的方法(4??):
public func subscribe ( _ on
: @escaping
( Event < E
> ) - > Void ) - > Disposable { let observer
= AnonymousObserver { e
in on ( e
) } return self . asObservable ( ) . subscribe ( observer
) }
代碼創(chuàng)建了一個觀察者,當(dāng)前觀察者將會收到發(fā)送過來的消息,并由此通過閉包一層層傳到業(yè)務(wù)層:4?? -> 3?? -> 2?? -> 1?? ->業(yè)務(wù)層; 當(dāng)前 self 指向的是1??處創(chuàng)建并保存的 Observable 類型的 source 對象,因此該處 subscribe 所調(diào)用的即是 Produce 類中的 subscribe 方法,在方法內(nèi)部創(chuàng)建了 sink 對象,來觸發(fā)創(chuàng)建序列時實(shí)現(xiàn)的閉包,即代碼1??處所 create 后的閉包; 此時就到了業(yè)務(wù)層,通過 create 內(nèi)部實(shí)現(xiàn)的閉包 single 向內(nèi)部發(fā)送消息,再有 observer 調(diào)用 on 來向觀察者發(fā)送信號; 信號發(fā)送不做贅述,最終會到達(dá)4??處代碼的觀察者,此時再由閉包一層層向上傳遞,直到業(yè)務(wù)層的監(jiān)聽閉包。 序列的產(chǎn)生,訂閱,發(fā)送,接收還是由 Observable 來實(shí)現(xiàn)的,Single 只是對 Observable 做了封裝,去除了 onCompleted 的消息監(jiān)聽及消息發(fā)送。
三、Completable
Completable 是 Observable 的另外一個版本,不像 Observable 可以發(fā)出多個元素,它要么只能產(chǎn)生一個 completed 事件,要么產(chǎn)生一個 error 事件: 發(fā)出一個 completed 元素,或一個 error 事件; Completable 只能產(chǎn)生 completed 事件和 error 事件,沒有序列元素值產(chǎn)生。適用于只關(guān)心任務(wù)是否完成,而不需要在意任務(wù)返回值的情況,它和 Observable 有點(diǎn)相似。
let completableOB
= Completable . create
{ ( completable
) - > Disposable in print ( "completableOB 是否共享" ) completable ( . completed
) completable ( . error ( NSError . init ( domain
: "com.ydw.cn" , code
: 10086 , userInfo
: nil ) ) ) return Disposables . create ( ) } completableOB
. subscribe
{ ( reslut
) in print ( "訂閱:\( reslut) " ) } . disposed ( by
: disposeBag
) completableOB 是否共享訂閱
: completed
在 Competable.swift 下,在 PrimitiveSequenceType 擴(kuò)展中實(shí)現(xiàn)了序列的創(chuàng)建和訂閱,即信號轉(zhuǎn)發(fā)。Competable 的定義如下:
public enum CompletableTrait { } public typealias Completable = PrimitiveSequence < CompletableTrait , Swift . Never > public enum CompletableEvent { case error ( Swift . Error ) case completed
}
同樣,Completable 類也是 PrimitiveSequence 的別名,并聲明一個枚舉包含,error 和 completed 成員變量,限定了事件產(chǎn)生類型,都是對 Observable 序列的封裝,和 Single 一致,只是在訂閱階段對 .next 事件做了攔截。
四、Maybe
Maybe 是 Observable 的另外一個版本,它介于 Single 和 Completable 之間,它要么只能發(fā)出一個元素,要么產(chǎn)生一個completed 事件,要么產(chǎn)生一個 error 事件。 發(fā)出一個元素或者一個 completed 事件或者一個 error 事件; 如果可能需要發(fā)出一個元素,又可能不需要發(fā)出時,就可以使用 Maybe。
let maybeOB
= Maybe < Any > . create
{ ( maybe
) - > Disposable in print ( "maybe 是否共享" ) maybe ( . success ( "A" ) ) maybe ( . completed
) maybe ( . error ( NSError . init ( domain
: "com.ydw.cn" , code
: 10086 , userInfo
: nil ) ) ) return Disposables . create ( ) } maybeOB
. subscribe
{ ( reslut
) in print ( "訂閱:\( reslut) " ) } . disposed ( by
: disposeBag
) maybe 是否共享訂閱
: success ( "A" )
五、Driver
① Driver 使用
Driver 是一個精心準(zhǔn)備的特征序列,它主要是對需要在 UI 上做出響應(yīng)的序列進(jìn)行了封裝,簡化 UI 層的代碼。不過如果遇到的序列具有以下特征,也可以使用它: Driver 序列不會產(chǎn)生 error 事件; 在主線程中監(jiān)聽(一定要在 MainScheduler 中),會向新訂閱者發(fā)送上次發(fā)送過的元素,簡化 UI 層的代碼;
let result
= self . textFiled
. rx
. text
. orEmpty
. asDriver ( ) . throttle ( . milliseconds ( 500 ) ) . flatMap
{ self . dealwithData ( inputText
: $
0 ) . asDriver ( onErrorJustReturn
: "檢測到錯誤" ) } result
. map { "長度:\( ( $0 as ! String ) . count ) " } . drive ( self . label
. rx
. text
) . disposed ( by
: disposeBag
) result
. map { ( $
0 as ! String ) } . drive ( self . btn
. rx
. title ( ) ) . disposed ( by
: disposeBag
)
說明: asDriver() 將序列轉(zhuǎn)換為 Driver 序列; driver 將元素在主線程中綁定到 label 和 button 上。 相比非 driver 下的代碼實(shí)現(xiàn),Driver 序列省去了線程的設(shè)置,share 數(shù)據(jù)共享設(shè)置。
② Driver 的源碼分析
查看 asDriver() 方法,是 ControlProperty 的擴(kuò)展方法,返回了一個Driver類:
extension ControlProperty { public func asDriver ( ) - > Driver < E
> { return self . asDriver
{ _ - > Driver < E
> in #
if DEBUG rxFatalError ( "Somehow driver received error from a source that shouldn't fail." ) #
else return Driver . empty ( ) #endif
} }
}
Driver 是 SharedSequence 的別名,用來描述不同類型的序列,最后又調(diào)用了 asDriver 方法,而該方法在 ObservableConvertibleType 的擴(kuò)展中,一直追蹤會發(fā)現(xiàn)很多類都是繼承自 ObservableConvertibleType 下:
extension ObservableConvertibleType { public func asDriver ( onErrorRecover
: @escaping
( _ error
: Swift . Error ) - > Driver < E
> ) - > Driver < E
> { let source
= self . asObservable ( ) . observeOn ( DriverSharingStrategy . scheduler
) . catchError
{ error
in onErrorRecover ( error
) . asObservable ( ) } return Driver ( source
) } }
如上,代碼也設(shè)置了 observerOn 方法,來指定線程,繼續(xù)深入能夠發(fā)現(xiàn) DriverSharingStrategy.scheduler 內(nèi)部指定的就是主線程,印證了上面所說的 Driver 的執(zhí)行是在主線程的,最后初始化一個 Driver 對象返回,看一下初始化過程,及對 SharedSequence 類的初始化,代碼如下:
public struct SharedSequence < S
: SharingStrategyProtocol , Element > : SharedSequenceConvertibleType { public typealias E
= Element public typealias SharingStrategy = S
let _source
: Observable < E
> init ( _ source
: Observable < E
> ) { self . _source
= S
. share ( source
) } }
此處調(diào)用了 share 并傳入了可觀察序列,感覺好像在哪見過,此處猜想它是用來共享序列的,使用 lldb:po S.self 查找 share 所在位置:RxCocoa.DriverSharingStrategy,cmd + 點(diǎn)擊進(jìn)入,代碼如下:
public typealias Driver < E
> = SharedSequence < DriverSharingStrategy , E
> public struct DriverSharingStrategy : SharingStrategyProtocol { public static var scheduler
: SchedulerType { return SharingScheduler . make ( ) } public static func share
< E
> ( _ source
: Observable < E
> ) - > Observable < E
> { return source
. share ( replay
: 1 , scope
: . whileConnected
) } }
在此處傳入的序列用來掉用 share,使得當(dāng)前序列作為共享序列,即 driver 序列為共享序列。
六、Signal
Signal 和 Driver 相似,唯一的區(qū)別是,Driver 會對新觀察者回放(重新發(fā)送)上一個元素,而 Signal 不會對新觀察者回放上一個元素。 一定在 MainScheduler 監(jiān)聽(主線程監(jiān)聽);
let result
= self . textFiled
. rx
. text
. orEmpty
. asSignal ( onErrorJustReturn
: "沒有值" ) . throttle ( . milliseconds ( 500 ) ) . flatMap
{ self . dealwithData ( inputText
: $
0 ) . asSignal ( onErrorJustReturn
: "檢測到錯誤" ) } result
. map { "長度:\( ( $0 as ! String ) . count ) " } . emit ( to
: self . label
. rx
. text
) . disposed ( by
: disposeBag
) result
. map { ( $
0 as ! String ) } . emit ( to
: self . btn
. rx
. title ( ) ) . disposed ( by
: disposeBag
)
說明: catchErrorJustReturn(onErrorJustReturn) 保證了無錯誤信號; observeOn(DriverSharingStrategy.scheduler) 保證了調(diào)度環(huán)境在主線程; source.share(scope: .whileConnected) 序列狀態(tài)共享。
七、ControlEvent
ControlEvent: 專門用于描述 UI 控件所產(chǎn)生的事件,它具有以下特征: 一定在 MainScheduler 訂閱(主線程訂閱); 一定在 MainScheduler 監(jiān)聽(主線程監(jiān)聽);
let controlEventOB
= button
. rx
. controlEvent ( . touchUpInside
) controlEventOB
. subscribe
{ ( reslut
) in print ( "訂閱:\( reslut) \n \( Thread . current) " ) } . disposed ( by
: disposeBag
) controlEventOB
. subscribe
{ ( reslut
) in print ( "訂閱:\( reslut) \n \( Thread . current) " ) } . disposed ( by
: self . disposeBag
)
let event
: ControlEvent < Void > = button
. rx
. tap
. asControlEvent ( ) event
. bind ( onNext
: { print ( "controllerEvent" ) } ) . disposed ( by
: disposeBag
)
監(jiān)聽點(diǎn)擊事件并綁定數(shù)據(jù)到其他 UI:
let event
: ControlEvent < Void > = button
. rx
. tap
. asControlEvent ( ) event
. map { "yahibo" } . bind ( to
: label1
. rx
. text
) . disposed ( by
: disposeBag
)
八、binder
不會處理錯誤事件; 確保綁定都是在給定 Scheduler 上執(zhí)行(默認(rèn) MainScheduler); 一旦產(chǎn)生錯誤事件,在調(diào)試環(huán)境下將執(zhí)行 fatalError,在發(fā)布環(huán)境下將打印錯誤信息。
let observer
: AnyObserver < Bool > = AnyObserver { ( event
) in print ( "observer當(dāng)前線程:\( Thread . current) " ) switch event
{ case . next ( let isHidden
) : print ( "label的狀態(tài)" ) self . label
. isHidden
= isHidden
case . error ( let error
) : print ( "\( error) " ) case . completed
: print ( "完成" ) } } let binder
= Binder < Bool > ( self . label
) { ( lab
, isHidden
) in print ( "Binder當(dāng)前線程:\( Thread . current) " ) lab
. isHidden
= isHidden
} let observable
= Observable < Bool > . create
{ ( ob
) - > Disposable in ob
. onNext ( true ) ob
. onError ( NSError . init ( domain
: "com.ydw.cn" , code
: 10086 , userInfo
: nil ) ) ob
. onCompleted ( ) return Disposables . create ( ) } . observeOn ( ConcurrentDispatchQueueScheduler ( queue
: DispatchQueue . global ( ) ) ) observable
. bind ( to
: binder
) . disposed ( by
: self . disposeBag
)
RxSwift 里面也封裝了很多的 binder,開發(fā)使用很直接:
extension Reactive where Base : UIButton { public func title ( for controlState
: UIControl . State = [ ] ) - > Binder < String ? > { return Binder ( self . base
) { button
, title
- > Void in button
. setTitle ( title
, for : controlState
) } } public func image ( for controlState
: UIControl . State = [ ] ) - > Binder < UIImage ? > { return Binder ( self . base
) { button
, image
- > Void in button
. setImage ( image
, for : controlState
) } } public func backgroundImage ( for controlState
: UIControl . State = [ ] ) - > Binder < UIImage ? > { return Binder ( self . base
) { button
, image
- > Void in button
. setBackgroundImage ( image
, for : controlState
) } } }
總結(jié)
以上是生活随笔 為你收集整理的RxSwift之深入解析场景特征序列的使用和底层实现 的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔 推薦給好友。