用于observeValue的Swift 4方法(forKeyPath:...)

MXV*_*MXV 36 key-value-observing swift swift4 keypaths

我一直试图找到一个例子,但我所看到的并不适用于我的情况.

什么是以下代码的等价物:

object.addObserver(self, forKeyPath: "keyPath", options: [.new], context: nil)

override public func observeValue(
    forKeyPath keyPath: String?,
    of object: Any?, 
    change: [NSKeyValueChangeKey : Any]?, 
    context: UnsafeMutableRawPointer?) {

}
Run Code Online (Sandbox Code Playgroud)

上面的代码有效,但我从SwiftLink收到警告:

使用Swift 3.2或更高版本时,首选基于新块的KVO API和键路径.

如果你能指出我正确的方向,我感激不尽.

Mat*_*eno 85

Swift 4引入了一系列具体的Key-Path类型,一个新的Key-Path Expression来生成它们,以及一个新的基于闭包的观察函数,可用于继承的类NSObject.

使用这组新功能,您现在可以更简洁地表达您的特定示例:

self.observation = object.observe(\.keyPath) { 
    [unowned self] object, change in
    self.someFunction()
}
Run Code Online (Sandbox Code Playgroud)

涉及的类型

密钥路径语法

一般语法密钥路径表达的如下形式\Type.keyPath,其中Type是一个具体的类型名称(包括任何通用参数),和keyPath一个或多个属性,下标,或可选的链接/被迫展开后缀的链.此外,如果可以从上下文推断出keyPath的类型,则可以省略它,从而导致最精辟\.keyPath.

这些都是有效的密钥路径表达式:

\SomeStruct.someValue
\.someClassProperty
\.someInstance.someInnerProperty
\[Int].[1]
\[String].first?.count
\[SomeHashable: [Int]].["aStringLiteral, literally"]!.count.bitWidth
Run Code Online (Sandbox Code Playgroud)

所有权

你是所有者NSKeyValueObservation实例observe函数返回,这意味着,你不必 addObserver也不是removeObserver了; 相反,只要您需要进行观察观察,就可以对它进行强有力的参考.

也不需要invalidate():它deinit优雅.所以,你可以让它存在直到持有它的实例死掉,通过nil引用手动停止它,或者invalidate()如果你因为某些臭的原因需要让你的实例保持活着,甚至可以调用它.

注意事项

您可能已经注意到,观察仍然隐藏在Cocoa的KVO机制的范围内,因此它只适用于Obj-C类和Swift类继承NSObject(每个Swift-dev的最喜欢的类型),并且要求您想要观察的任何值,必须标记为@objc(每个Swift-dev最喜欢的属性)并声明dynamic.

话虽这么说,整体机制是一个受欢迎的改进,特别是因为它设法NSObjects从我们可能碰巧需要使用的模块中导入的Swiftify观察(例如Foundation),并且没有冒着削弱我们努力获得的表现力的风险.按键.

作为附注,仍然需要Key-Path String Expressions动态访问 NSObject KVC或调用的属性value(forKey(Path):)

超越KVO

关键路径表达式比KVO要多得多.\Type.path表达式可以存储为KeyPath对象以供以后重用.它们有可写,部分和类型擦除的味道.它们可以增强为构图设计的getter/setter函数的表现力,更不用说它们在允许那些胃部最强的人钻研透镜和棱镜等功能概念的世界中扮演的角色.我建议你查看下面的链接,了解他们可以打开的许多开发门的更多信息.

链接:

密钥路径表达式@ docs.swift.org

KVO docs @ Apple

Swift Evolution智能KeyPaths提案

Ole Begemann的Whats-new-in-Swift-4游乐场,带有Key-Path示例

WWDC 2017视频: SKP 基础4:35和KVO 19:40 新增内容.


bar*_*ity 7

在iOS 10中使用此方法时,当我遇到我的应用程序崩溃时要在答案中添加一些内容。

在iOS 10中,您仍然需要在取消分配类之前删除观察者,否则您将崩溃,NSInternalInconsistencyException说明:

A类的实例C被释放,而键值观察器仍在注册。

为了避免这种崩溃。只需将您要使用的观察者属性设置为即可nil

deinit {
    self.observation = nil
}    
Run Code Online (Sandbox Code Playgroud)

  • 通知也是同样的问题。如果使用基于块的方法,则需要在deinit中将返回值显式设置为nil。非基于块的观察者不需要这样做。 (2认同)