Swift 4(BETA 2)KVO崩溃,基于WWDC谈话
我试图得到一些非常类似于WWV 2017基金会谈论KVO观察的例子.我看到的唯一不同于那次谈话的差异是,我不得不调用super.init(),我不得不隐藏地解开“kvo”令牌.
以下用于游乐场: struct Node { let title: String let leaf: Bool var children: [String: Node] = [:] } let t = Node(title:"hello",leaf:false,children:[:]) let k1 = Node.leaf let k2 = Node.children t[keyPath: k1] // returns "false" works t[keyPath: k2] // returns "[:]" works @objcMembers class MyController : NSObject { dynamic var tr: Node var kvo : NSKeyValueObservation! init(t: Node) { tr = t super.init() kvo = observe(.tr) { object,change in print("(object) (change)") } } } let x = MyController(t: t) x.tr = Node(title:"f",children:[:]) x 这个错误:
另外,请看到此错误:
是否有其他人能够得到这样的工作,或者这是我需要报告的错误?
这里的错误是编译器让你说:
@objcMembers class MyController : NSObject { dynamic var tr: Node // ... Node是一个结构,因此不能直接用Obj-C表示.但是,编译器仍允许您将tr标记为动态 – 这需要@objc.虽然@objcMembers推断@objc为类的成员,但它只对可直接表示在Obj-C中的成员这样做,而tr则不是. 所以真的,编译器不应该让你把tr标记为动态 – 我继续前进到filed a bug here,其中has now been fixed将为Swift 5做好准备. tr需要成为@objc&动态为你使用KVO,因为KVO需要方法调配,Obj-C运行时提供,而Swift运行时则不需要.所以要在这里使用KVO,你需要使Node成为一个类,并从NSObject继承,以便将tr暴露给Obj-C: class Node : NSObject { let title: String let leaf: Bool var children: [String: Node] = [:] init(title: String,leaf: Bool,children: [String: Node]) { self.title = title self.leaf = leaf self.children = children } } (如果你再次看一下WWDC视频,你会看到他们观察的属性实际上是一个继承自NSObject的类的类型) 但是,在您给出的示例中,您并不真正需要KVO – 您可以将Node保留为结构,而是使用属性观察器: struct Node { let title: String let leaf: Bool var children: [String: Node] = [:] } class MyController : NSObject { var tr: Node { didSet { print("didChange: (tr)") } } init(t: Node) { tr = t } } let x = MyController(t: Node(title:"hello",children: [:])) x.tr = Node(title:"f",leaf: false,children: [:]) // didChange: Node(title: "f",children: [:]) 而且因为Node是一个值类型,didSet也会触发对其属性的任何更改: x.tr.children["foo"] = Node(title: "bar",children: [ // "foo": kvc_in_playground.Node(title: "bar",children: [:]) // ]) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |