返回 导航

Swift

hangge.com

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)

回到顶部