不久前我遇到了同样的问题。
最后,我为状态使用了一个枚举,并添加了一个额外的“原始”属性,该属性由属性观察者在主状态属性上设置。
您可以对“原始”属性进行 KVO,然后在其更改时引用真正的枚举属性。
这显然是一种 hack,但对我来说,这比完全放弃枚举并失去所有好处要好。
例如。
class Model : NSObject {
enum AnEnumType : String {
case STATE_A = "A"
case STATE_B = "B"
}
dynamic private(set) var enumTypeStateRaw : String?
var enumTypeState : AnEnumType? {
didSet {
enumTypeStateRaw = enumTypeState?.rawValue
}
}
}
补充:
如果您正在编写在 Swift 中进行观察的类,这里有一个方便的实用程序类可以消除一些痛苦。
好处是:
- 您的观察者无需继承 NSObject。
- 观察回调代码作为闭包而不是必须实现
观察ValueForKeyPath:BlahBlah...
- 无需确保您删除Observer,它会为您处理好。
实用程序类称为KVOObserver,示例用法是:
class ExampleObserver {
let model : Model
private var modelStateKvoObserver : KVOObserver?
init(model : Model) {
self.model = model
modelStateKvoObserver = KVOObserver.observe(model, keyPath: "enumTypeStateRaw") { [unowned self] in
println("new state = \(self.model.enumTypeState)")
}
}
}
在捕获列表中注明[unowned self]以避免引用循环。
这里是KVOObserver...
class KVOObserver: NSObject {
private let callback: ()->Void
private let observee: NSObject
private let keyPath: String
private init(observee: NSObject, keyPath : String, callback: ()->Void) {
self.callback = callback
self.observee = observee
self.keyPath = keyPath;
}
deinit {
println("KVOObserver deinit")
observee.removeObserver(self, forKeyPath: keyPath)
}
override func observeValueForKeyPath(keyPath: String,
ofObject object: AnyObject,
change: [NSObject : AnyObject],
context: UnsafeMutablePointer<()>) {
println("KVOObserver: observeValueForKey: \(keyPath), \(object)")
self.callback()
}
class func observe(object: NSObject, keyPath : String, callback: ()->Void) -> KVOObserver {
let kvoObserver = KVOObserver(observee: object, keyPath: keyPath, callback: callback)
object.addObserver(kvoObserver, forKeyPath: keyPath, options: NSKeyValueObservingOptions.New | NSKeyValueObservingOptions.Initial, context: nil)
return kvoObserver
}
}