Swift 4 approach for observeValue(forKeyPath:...)



>我一直在试图找到一个例子,但我所看到的在我的情况下不起作用。

相当于以下代码:

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。

如果您能指出我正确的方向,我将不胜感激。

Swift 4 引入了一系列具体的键路径类型、一个新的键路径表达式来生成它们,以及一个新的基于闭包的观察函数,可用于继承NSObject的类。

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

self.observation = object.observe(.keyPath) { 
[unowned self] object, change in
self.someFunction()
}

涉及的类型

  • observation:NSKeyValueObservation
  • change:NSKeyValueObservedChange
  • .keyPath:编译时生成的 KeyPath 类的实例。

键路径语法

键路径表达式的一般语法遵循以下形式Type.keyPath其中Type是具体的类型名称(包括任何泛型参数),keyPath一个或多个属性、下标或可选链接/强制解包后缀的链。此外,如果可以从上下文中推断出 keyPath 的类型,则可以省略它,从而产生最简洁的.keyPath

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

SomeStruct.someValue
.someClassProperty
.someInstance.someInnerProperty
[Int].[1]
[String].first?.count
[SomeHashable: [Int]].["aStringLiteral, literally"]!.count.bitWidth

所有权

你是observe函数返回的NSKeyValueObservation实例的所有者,这意味着,你不必addObserver也不必再removeObserver;相反,只要你需要观察观察,你就保持对它的强引用。

您也不需要invalidate():它会优雅地deinit。因此,您可以让它存活直到持有它的实例死亡,通过nil引用手动停止它,或者如果您出于某种臭原因需要保持实例处于活动状态,甚至可以调用invalidate()

警告

您可能已经注意到,观察仍然潜伏在 Cocoa 的 KVO 机制范围内,因此它仅适用于继承NSObject的 Obj-C 类和 Swift 类(每个 Swift-dev 最喜欢的类型),并增加了一个要求,即您打算观察的任何值都必须标记为@objc(每个 Swift-dev 最喜欢的属性)并声明dynamic

话虽如此,整体机制是一个受欢迎的改进,特别是因为它设法 Swiftify 观察我们可能碰巧需要使用的模块导入NSObjects(例如。Foundation),并且不会削弱我们努力通过每次击键获得的表现力。

作为旁注,仍然需要键路径字符串表达式来动态访问NSObject的属性到 KVC 或调用value(forKey(Path):)

超越韩国国际空间组织

键路径表达式比 KVO 要多得多。Type.path表达式可以存储为KeyPath对象以供以后重用。它们有可写、部分和类型擦除的口味。它们可以增强专为构图设计的吸气/二传手功能的表现力,更不用说它们在让胃部最强的人深入研究镜片和棱镜等功能概念的世界方面所扮演的角色。我建议您查看下面的链接,以了解有关他们可以打开的许多开发之门的更多信息。

链接:

键路径表达式 @ docs.swift.org

KVO docs @ Apple

Swift Evolution Smart KeyPath 提案

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

WWDC 2017 视频:基金会新增功能SKP 4:35 和 KVO 19:40。

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

在 iOS 10 中,您仍然需要在解除分配类之前删除观察器,否则您将收到崩溃NSInternalInconsistencyException指出:

C的实例A被解除分配,而键值观察者仍在其中注册。

为了避免这种崩溃。只需设置用于nil的观察者属性。

deinit {
self.observation = nil
}    

相关内容

  • 没有找到相关文章

最新更新