Swift - RxSwift的使用详解61(sendMessage和methodInvoked的区别)
作者:hangge | 2018-05-15 08:10
一、基本介绍
1,sendMessage 与 methodInvoked 的区别
(1)在之前的几篇文章中,我用到了 methodInvoked 这个 Rx 扩展方法,其作用是获取代理方法执行后产生的数据流。
(2)除了 methodInvoked 外,还有个 sentMessage 方法也有同样的作用,它们间只有一个区别:
- sentMessage 会在调用方法前发送值。
- methodInvoked 会在调用方法后发送值。
2,实现原理
(1)其原理简单说就是利用 Runtime 消息转发机制来转发代理方法。同时在调用返回值为空的代理方法的前后分别产生两种数据流。
(2)比如最开始的代理为 A,然后我们把代理改为 AProxy,并把 A 设置为 AProxy 的 _forwardToDelegate。这样所有的代理方法将会变成到达 AProxy,接着 AProxy 对这些方法进行如下操作:
- 首先调用 sentMessage 方法
- 接着调用原代理方法
- 最后调用 methodInvoked 方法
二、使用样例
我们分别通过 sendMessage 以及 methodInvoked 方法来获取 selector 对应的 Observable,并将它们与原方法做比较,看看执行的先后顺序。
(注意:两个样例中 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)
}
//默认的viewWillAppear方法
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
print("2")
}
}
运行结果如下:
样例2:拦截自定义方法
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
//使用sentMessage获取方法执行前的序列
self.rx.sentMessage(#selector(ViewController.test))
.subscribe(onNext: { value in
print("1:\(value[0])")
})
.disposed(by: disposeBag)
//使用methodInvoked获取方法执行后的序列
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)
//调用自定义方法
test("hangge.com")
}
//自定义方法
@objc dynamic func test(_ value:String) {
print("2:\(value)")
}
}
//转类型的函数(转换失败后,会发出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
}
运行结果如下:
全部评论(0)