RxSwift:KVO監聽對象屬性

在觀察某個屬性是否變化的時候,採用 KVO 的方式更爲簡單直接一些。swift

關於 Swift 的 KVO 使用方法,能夠查看王巍的 KVObash

簡單來講,在 Swift 中:框架

  • 被觀察的屬性前須要添加 @objc dynamic 標籤,
  • 被觀察的類必須繼承 NSObject

若是不符合則會發生如下異常:ide

sent to an object that is not KVC-compliant for the "***" property.
複製代碼

在 RxSwift 框架下,提供了 rx.observerx.observeWeakly 兩種方式的課觀察序列。性能

rx.observe

rx.observe 是對 KVO 的簡單封裝,執行效率更高。它要求被觀察的屬性路徑都是使用 strong 修飾的,若是觀察使用 weak 修飾的屬性,可會發生崩潰。ui

使用 rx.observe 時,須要注意 循環引用 的問題。若是一個類觀察本身的屬性,使用 rx.observe 將會產生 循環引用 的問題。spa

rx.observeWeakly

rx.observeWeakly 能夠處理屬性變爲空的狀況,全部能夠用在使用 weak 修飾的屬性上。debug

全部能夠使用 rx.observe 的地方,都是使用 rx.observeWeakly。可是,rx.observeWeakly 的性能沒有 rx.observe 的高。code

下面爲採用 RxSwift 框架下的實例:繼承

import RxCocoa
import RxSwift

class User: NSObject {
    @objc dynamic var name: String
    
    init(name: String) {
        self.name = name
    }
}

class TestViewController: UIViewController {

    @objc dynamic var message = ""
    var disposeBag = DisposeBag()
    @objc dynamic var user: User = User(name: "fang")
    @objc dynamic var number: Int = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .orange
        
        let interval: DispatchTimeInterval = .seconds(1)
        Observable<Int>
            .interval(interval, scheduler: MainScheduler.instance)
            .subscribe(onNext: { [unowned self] (_) in
                self.number += 1
                self.user.name += "~"
            })
            .disposed(by: disposeBag)
        
        // 監聽 number 屬性
        self.rx
            .observeWeakly(Int.self, "number")
            .subscribe(onNext: { (message) in
                // 注意: number 爲 Int? 類型
                debugPrint(message ?? -1)
            })
            .disposed(by: disposeBag)

        // 監聽 user.name 屬性
        self.rx
            .observeWeakly(String.self, "user.name")
            .subscribe(onNext: { (name) in
                // 注意: name 爲 Sting? 類型
                debugPrint(name ?? "")
            })
            .disposed(by: disposeBag)
        
    }
}

複製代碼

注意

在實例中,觀察 user.name 屬性時,keypath 中的 username 屬性都要使用 @objc dynamic 進行標記。

也就是說 TestViewController 中的 user 屬性須要使用 @objc dynamic 進行標記,User 類中的 name 屬性,也要用 @objc dynamic 進行標記。

在實例中,必須使用 rx.observeWeakly 進行監聽,不然會產生循環應用。

其餘

Swift 3 中繼承自 NSObject 的類,不須要手動添加 @objc ,編譯器會給全部的非 private 的類和成員加上 @objc , private 接口想要暴露給 Objective-C 須要 @objc 的修飾。Swift4 後繼承自 NSObject 的類再也不隱式添加 @objc 關鍵字

相關文章
相關標籤/搜索