我一直试图找到一个例子,但我所看到的并不适合我的情况。
以下代码的等效内容:
object.addObserver(self, forKeyPath: "keyPath", options: [.new], context: nil)
override public func observeValue(
forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?) {
}
上面的代码有效,但我收到了SwiftLink的警告:
在使用Swift 3.2或更高版本时,首选基于新块的KVO API和键路径。
如果你能指出我正确的方向,我感激不尽。
答案 0 :(得分:69)
Swift 4引入了一系列具体的Key-Path types,一个新的Key-Path Expression来生成它们,以及一个新的基于闭包的observe函数可用于继承NSObject
的类。 / p>
使用这组新功能,您现在可以更简洁地表达您的特定示例:
self.observation = object.observe(\.keyPath) {
[unowned self] object, change in
self.someFunction()
}
涉及的类型
observation:
NSKeyValueObservation
change:
NSKeyValueObservedChange
\.keyPath
:编译时生成的KeyPath类的实例。密钥路径语法
密钥路径表达式的一般grammar遵循\Type.keyPath
形式,其中Type
是具体类型名称(包括任何通用参数),keyPath
a一个或多个属性,下标或可选链接/强制解包后缀的链。此外,如果可以从上下文推断出keyPath的类型,则可以省略它,从而产生最精悍的\.keyPath
。
这些都是有效的密钥路径表达式:
\SomeStruct.someValue
\.someClassProperty
\.someInstance.someInnerProperty
\[Int].[1]
\[String].first?.count
\[SomeHashable: [Int]].["aStringLiteral, literally"]!.count.bitWidth
<强>所有权强>
您是NSKeyValueObservation
函数返回的observe
实例的所有者,这意味着您不必 addObserver
也不会{{1}不再相反,只要您需要进行观察观察,就可以对它进行强有力的参考。
removeObserver
也不需要 :优雅地invalidate()
。所以,你可以让它存在直到持有它的实例死掉,通过deinit
引用手动停止它,或者如果你因为某些臭的原因需要让你的实例保持活着,甚至可以调用nil
。 p>
<强>注意事项强>
您可能已经注意到,观察仍然潜藏在Cocoa的KVO机制范围内,因此它只适用于Obj-C类和Swift类继承invalidate()
(每个Swift-dev最喜欢的类型)并增加了要求您想要观察的任何值必须标记为NSObject
(每个Swift-dev最喜欢的属性)并声明为@objc
。
话虽这么说,整体机制是一个受欢迎的改进,特别是因为它设法Swiftify从我们可能碰巧需要使用的模块中观察导入的dynamic
(例如NSObjects
),并且没有冒着削弱我们每次按键时难以获得的表现力的风险。
作为旁注,Key-Path String Expressions Foundation
的属性仍然需要dynamically access给KVC或致电NSObject
超越KVO
Key-Path Expressions比KVO还要多得多。 value(forKey(Path):)
表达式可以存储为\Type.path
个对象,以便以后重用。它们有可写,部分和类型擦除的味道。它们可以增强为构图设计的getter / setter函数的表现力,更不用说它们在允许那些胃部最强的人钻研透镜和棱镜等功能概念的世界中扮演的角色。我建议你查看下面的链接,了解他们可以打开的许多开发门的更多信息。
<强>链接:强>
Key-Path Expression @ docs.swift.org
Swift Evolution Smart KeyPaths proposal
Ole Begemann's Whats-new-in-Swift-4 playground with Key-Path examples
SKP的WWDC 2017 Video: What's New in Foundation 4:35,KVO的时间是19:40。
答案 1 :(得分:6)
在iOS 10中使用此方法时,我的应用程序崩溃时要在答案中添加一些内容。
在iOS 10中,您仍然需要在取消分配类之前除去观察者,否则将发生崩溃NSInternalInconsistencyException
并指出:
类别
A
的实例C
被释放,而键值观察者仍在注册。
为避免此崩溃。只需将您使用的观察者属性设置为nil
。
deinit {
self.observation = nil
}