一延蟹、基本介紹
1,sendMessage 與 methodInvoked 的區(qū)別
(1)在之前的幾篇文章中叶堆,我用到了 methodInvoked
這個(gè) Rx
擴(kuò)展方法阱飘,其作用是獲取代理方法執(zhí)行后產(chǎn)生的數(shù)據(jù)流。
- Swift - RxSwift的使用詳解19(特征序列3:ControlProperty虱颗、 ControlEvent)
- Swift - RxSwift的使用詳解58(DelegateProxy樣例1:獲取地理定位信息 )
- Swift - RxSwift的使用詳解59(DelegateProxy樣例2:圖片選擇功能 )
- Swift - RxSwift的使用詳解60(DelegateProxy樣例3:應(yīng)用生命周期的狀態(tài)變化)
(2)除了 methodInvoked
外沥匈,還有個(gè) sentMessage
方法也有同樣的作用,它們間只有一個(gè)區(qū)別:
-
sentMessage
會(huì)在調(diào)用方法前發(fā)送值忘渔。 -
methodInvoked
會(huì)在調(diào)用方法后發(fā)送值高帖。
2,實(shí)現(xiàn)原理
(1)其原理簡(jiǎn)單說就是利用 Runtime
消息轉(zhuǎn)發(fā)機(jī)制來轉(zhuǎn)發(fā)代理方法畦粮。同時(shí)在調(diào)用返回值為空的代理方法的前后分別產(chǎn)生兩種數(shù)據(jù)流散址。
(2)比如最開始的代理為 A,然后我們把代理改為 AProxy
宣赔,并把 A 設(shè)置為 AProxy
的_forwardToDelegate
预麸。這樣所有的代理方法將會(huì)變成到達(dá) AProxy
,接著 AProxy
對(duì)這些方法進(jìn)行如下操作:
- 首先調(diào)用
sentMessage
方法 - 接著調(diào)用原代理方法
- 最后調(diào)用
methodInvoked
方法
二儒将、使用樣例
我們分別通過 sendMessage
以及 methodInvoked
方法來獲取 selector
對(duì)應(yīng)的 Observable
吏祸,并將它們與原方法做比較,看看執(zhí)行的先后順序钩蚊。
(注意:兩個(gè)樣例中 selector
都不是代理方法贡翘,但不影響效果的演示。)
樣例1:攔截 VC 的 viewWillAppear 方法
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
//使用sentMessage方法獲取Observable
self.rx.sentMessage(#selector(ViewController.viewWillAppear(_:)))
.subscribe(onNext: { value in
print("1")
})
.disposed(by: disposeBag)
//使用methodInvoked方法獲取Observable
self.rx.methodInvoked(#selector(ViewController.viewWillAppear(_:)))
.subscribe(onNext: { value in
print("3")
})
.disposed(by: disposeBag)
}
//默認(rèn)的viewWillAppear方法
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
print("2")
}
}
運(yùn)行結(jié)果如下:
樣例2:攔截自定義方法
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
//使用sentMessage獲取方法執(zhí)行前的序列
self.rx.sentMessage(#selector(ViewController.test))
.subscribe(onNext: { value in
print("1:\(value[0])")
})
.disposed(by: disposeBag)
//使用methodInvoked獲取方法執(zhí)行后的序列
self.rx.methodInvoked(#selector(ViewController.test))
.map({ (a) in
return try castOrThrow(String.self, a[0])
})
.subscribe(onNext: { value in
print("3:\(value)")
})
.disposed(by: disposeBag)
//調(diào)用自定義方法
test("hangge.com")
}
//自定義方法
@objc dynamic func test(_ value:String) {
print("2:\(value)")
}
}
//轉(zhuǎn)類型的函數(shù)(轉(zhuǎn)換失敗后砰逻,會(huì)發(fā)出Error)
fileprivate func castOrThrow<T>(_ resultType: T.Type, _ object: Any) throws -> T {
guard let returnValue = object as? T else {
throw RxCocoaError.castingError(object: object, targetType: resultType)
}
return returnValue
}
運(yùn)行結(jié)果如下: