觀察者模式 在iOS開發(fā)中應用相當廣泛,即:Key-Value Observing,它提供一種機制,當指定的對象的屬性(相應的keyPath)被修改后,則對象就會接受到通知。簡單的說就是每次指定的被觀察的對象的屬性被修改后,KVO就會自動通知相應的觀察者。
swift中使用KVO要比OC中稍顯局限:
- NSObject的子類:觀察者和被觀察者都必須是 NSObject 的子類。 因為OC中KVO的實現基于 KVC 和 runtime 機制,只有是 NSObject 的子類才能利用這些特性。
- @dynamic:觀察的自定義類的屬性需要使用 @dynamic 關鍵字修飾。
以上這兩個條件,就使得以往OC中的使用KVO來觀察某個枚舉屬性的type的變化,在swift中就行不通,當然還包括了swift中的結構體以及泛型。
下面來看下swift中實現kvo
自定義類
import UIKit
class FLObbserve: NSObject {
dynamic var name:String? //dynamic 修飾屬性 表示該屬性的存取都由 runtime 在運行時來決定
override init() {
name = "123"
super.init()
addObserver(self, forKeyPath: "name", options: .new, context: nil)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
print("kvo is valid")
}
deinit {
removeObserver(self, forKeyPath: "name")
}
}
運行后,外部修改name屬性,控制臺打印結果:
kvo is valid
由此在實現了上述兩個條件后,為自定義類添加了kvo。
那么對于Struct,Enum這些值類型的如何實現觀察者模式呢?
這邊我們就要引入一個屬性觀察器的概念:
Swift 中可以為一個屬性設置屬性觀察器,可以說是內建的 KVO 觀察,只不過只限于對自身屬性的觀察。
看下代碼:
//MARK: 設置自定義屬性的屬性觀察器
var direction:Direction {
willSet{ // direction屬性變化前要執(zhí)行事件
}
didSet { // direction屬性變化后要執(zhí)行事件
changeDirection(direction: direction)
}
}
其中,Direction是自定義的枚舉
屬性觀察器只在在初始化完成后觸發(fā),而且不限于 NSObject 的子類,Swift 中所有的 Class, Struct, Enum 都可以使用。
其中,Array, Dictionary, Set 等值類型,對其內容的修改(增/刪/替換)元素也會觸發(fā)屬性觀察器。因為Array、Dictionary、Set 等值類型更改內容后,會將新的內容復制到變量,變量的地址也發(fā)現變化。