Swift - RxSwift的使用詳解61(sendMessage和methodInvoked的區別)

一、基本介紹

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
}

運行結果如下:

RxSwift使用詳解系列
原文出自:www.hangge.com轉載請保留原文鏈接

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容