在符合协议的对象上执行Swift KVO

时间:2019-06-11 16:44:23

标签: swift protocols key-value-observing

我有一个协议(X)和一个实现协议X的类(A):

protocol X, NSObjectProtocol {
   var toBeObserved: MyCustomClass? { get}
}

class A: NSObject, X {
   var toBeObserved: MyCustomClass?
   ...
}

在另一个类中,我要观察变量toBeObserved

class B {
    ...
    var instanceConformingToX: X <-note: not A but simply the protocol X
    ...
    func someFunc() {
       self.observation = self.observe(\.instanceConformingToX.toBeObserved) { (observed, change) in
       ...
       }
    } 
}

}

这里的所有方程式都是或符合NSObject的,因此我希望能够使用KVO toBeObserved,但会导致运行时崩溃:

Fatal error: Could not extract a String from KeyPath Swift.KeyPath<MyAppName.B, MyFramework.A>

谢谢。

1 个答案:

答案 0 :(得分:3)

确保将观察到的属性标记为@objcdynamic。正如Using Key-Value Observing in Swift所说:

  

使用@objc属性和dynamic修饰符标记要通过键值观察观察的属性。

协议和参与的课程也需要标记为@objc。例如:

class MyCustomClass: NSObject { ... }

@objc protocol X: NSObjectProtocol {
    @objc dynamic var toBeObserved: MyCustomClass? { get }
}

class A: NSObject, X {
    var toBeObserved: MyCustomClass? = MyCustomClass()
}

class B: NSObject {
    @objc var x: X = A()

    var token: NSKeyValueObservation?

    func addObserver() {
        token = observe(\.x.toBeObserved) { object, _ in
            print(object)
        }
    }
}