Swift 派生 属性 KVO 不工作问题

Swift derived property KVO not working issue

我正在尝试实现 NSCollectionViewItem class,它提供从 representedObject 派生的只读 属性,简化代码如下所示

class PersonItem : NSCollectionViewItem {
   var fullName:String! {
        get {
            if let obj = representedObject as? Person {
                return "\(obj.firstName) \(obj.lastName)"
            }
            return "none"
        }
    }
}

我当然可以通过简单的方式获得价值

person.fullName

但是,我提供这个 属性 的原因是我想将它绑定到 xib 文件中的 UI。 KVO 似乎只适用于 representedObject 的变化,但如果值来自 fullName 属性,它根本不起作用。我注意到有一个 class 方法

keyPathsForValuesAffectingValueForKey

用于通知派生属性的更改,但我无法在 Swift class 中覆盖它。好像那里没有提供这个方法,它说找不到,即使 class 继承自 NSCollectionViewItem.

所以,问题是如何使 KVO 也适用于此 fullName 属性?

三件事:首先,正如评论中提到的 sunshine,您需要使用 dynamic 关键字标记您的 属性 以便使用键值编码访问它,这是先决条件用于键值观察。

其次,keyPathsForValuesAffectingValueForKey()是一种class方法。因此,要覆盖它,您必须使用:

override class func keyPathsForValuesAffectingValueForKey(_ key: String) -> Set<String> {
    // ...
}

第三,但是,不要那样做。来自 keyPathsForValuesAffectingValueForKey() 的文档:

The default implementation of this method searches the receiving class for a method whose name matches the pattern +keyPathsForValuesAffecting<Key>, and returns the result of invoking that method if it is found.

因此,更好的选择是实施:

dynamic class func keyPathsForValuesAffectingFullName() -> Set<String> {
    return ["representedObject.firstName", "representedObject.lastName"]
}

该方法也需要 dynamic,因为它是按名称查找的。