我很难使用Swift 4中新的强类型KVO语法来观察只能通过协议可见的属性:
import Cocoa
@objc protocol Observable: class {
var bar: Int { get }
}
@objc class Foo: NSObject, Observable {
@objc dynamic var bar = 42
}
let implementation = Foo()
let observable: Observable = implementation
let observation = observable.observe(\.bar, options: .new) { _, change in
guard let newValue = change.newValue else { return }
print(newValue)
}
implementation.bar = 50error: value of type 'Observable' has no member 'observe'
let observation = observable.observe(\.bar, options: .new) { _, change in显然,Observable不是NSObject。但我不能简单地将其转换为NSObject,因为键盘的类型将与对象的类型不匹配。
我试着更明确地说明这种类型:
let observable: NSObject & Observable = implementation但是:
error: member 'observe' cannot be used on value of protocol type 'NSObject & Observable'; use a generic constraint instead
let observation = observable.observe(\.bar, options: .new) { _, change in我想做的是不可能的吗?这似乎是一个常见的用例。用旧的#keypath语法可以很容易地完成。你能提供其他选择吗?谢谢。
发布于 2018-06-01 14:50:46
这段代码在Swift 4.1.2 (Xcode 9.4)中编译和运行:
import Foundation
@objc protocol Observable: AnyObject {
var bar: Int { get }
}
@objc class Foo: NSObject, Observable {
@objc dynamic var bar = 42
}
let implementation = Foo()
let observable: NSObject & Observable = implementation
func observeWrapper<T: NSObject & Observable>(_ object: T) -> NSKeyValueObservation {
return object.observe(\.bar, options: .new) { _, change in
guard let newValue = change.newValue else { return }
print(newValue)
}
}
let observation = observeWrapper(observable)
implementation.bar = 50
withExtendedLifetime(observation, {})我所做的就是将对observe的调用封装在一个受限于NSObject & Observable的泛型函数中。
尽管引入了泛型,但仍然可以将协议类型的observable传递给这个新函数。老实说,我不能真正解释为什么会这样。
编辑:这可能解释为:https://stackoverflow.com/a/43408193/116862,因此即使约束匹配,也不允许调用具有存在性(协议类型)的泛型函数。但是@objc协议有一个例外(没有静态需求),它们确实符合自己的要求。我认为这是因为Observable被标记为@objc__。
https://stackoverflow.com/questions/47199946
复制相似问题