Swift 4 引入了一系列具体的 Key-Path types、一个新的 Key-Path Expression 来生成它们,以及一个新的基于闭包的 observe 函数,可用于继承 NSObject 的类。
使用这组新功能,您的特定示例现在可以更简洁地表达:
self.observation = object.observe(\.keyPath) {
[unowned self] object, change in
self.someFunction()
}
涉及的类型
Key-Path 语法
Key-Path 表达式的一般grammar 遵循\Type.keyPath 的形式,其中Type 是具体类型名称(包括任何泛型参数),keyPath 是一个或多个属性、下标的链,或可选的链接/强制展开后缀。另外,如果keyPath的Type可以从context中推断出来,那么可以省略,从而得到一个最精炼的\.keyPath。
这些都是有效的键路径表达式:
\SomeStruct.someValue
\.someClassProperty
\.someInstance.someInnerProperty
\[Int].[1]
\[String].first?.count
\[SomeHashable: [Int]].["aStringLiteral, literally"]!.count.bitWidth
所有权
您是observe 函数返回的NSKeyValueObservation 实例的所有者,这意味着,您不必 addObserver 或removeObserver 了;相反,只要你需要观察观察,你就会一直强烈地引用它。
您也不需要invalidate():它会优雅地deinit。因此,您可以让它一直存活到持有它的实例死亡,也可以通过 niling 引用手动停止它,或者如果您出于某种臭名昭著的原因需要保持实例存活,甚至可以调用 invalidate()。
注意事项
您可能已经注意到,观察仍然潜伏在 Cocoa 的 KVO 机制的范围内,因此它仅适用于 Obj-C 类和继承 NSObject 的 Swift 类(每个 Swift-dev 最喜欢的类型),并附加要求任何您打算观察的值,必须标记为@objc(每个 Swift 开发人员最喜欢的属性)并声明为dynamic。
话虽如此,整体机制是一个值得欢迎的改进,特别是因为它设法 Swiftify 从我们可能碰巧需要使用的模块(例如Foundation)中观察导入的NSObjects,并且不会冒削弱表达能力的风险我们非常努力地在每次按键时获得力量。
附带说明,Key-Path String Expressions 仍然需要 dynamically access NSObject 的属性到 KVC 或调用 value(forKey(Path):)
KVO 之外
Key-Path Expressions 比 KVO 更多。 \Type.path 表达式可以存储为 KeyPath 对象以供以后重用。它们有可写、部分和类型擦除的味道。它们可以增强为合成而设计的 getter/setter 函数的表达能力,更不用说它们在让那些最有胆量的人深入研究 Lenses 和 Prisms 等功能概念世界中所起的作用。我建议您查看下面的链接,详细了解他们可以打开的许多开发门。
链接:
Key-Path Expression @ docs.swift.org
KVO docs @ Apple
Swift Evolution Smart KeyPaths proposal
Ole Begemann's Whats-new-in-Swift-4 playground with Key-Path examples
WWDC 2017 Video: What's New in FoundationSKP 为 4:35,KVO 为 19:40。