Свифт КВО на объекте, соответствующем протоколу - PullRequest
1 голос
/ 11 июня 2019

У меня есть протокол (X) и класс (A), который реализует протокол X:

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, поэтому я ожидаю, что смогу выполнить КВО toBeObserved, но вместо этого получаю аварийное завершение:

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

Спасибо.

1 Ответ

3 голосов
/ 11 июня 2019

Обязательно отметьте наблюдаемое свойство как @objc и dynamic. Как Использование наблюдения значения ключа в Swift говорит:

Отметьте свойства, которые вы хотите наблюдать посредством наблюдения значения ключа, с помощью атрибута @objc и модификатора dynamic.

Протокол и участвующие классы также должны быть помечены @objc. E.g.:

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)
        }
    }
}
...