Swift 4(BETA 2)KVO崩溃,基于WWDC谈话

前端之家收集整理的这篇文章主要介绍了Swift 4(BETA 2)KVO崩溃,基于WWDC谈话前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图得到一些非常类似于WWV 2017基金会谈论KVO观察的例子.我看到的唯一不同于那次谈话的差异是,我不得不调用super.init(),我不得不隐藏地解开“kvo”令牌.

以下用于游乐场:

  1. struct Node {
  2. let title: String
  3. let leaf: Bool
  4. var children: [String: Node] = [:]
  5. }
  6.  
  7. let t = Node(title:"hello",leaf:false,children:[:])
  8. let k1 = \Node.leaf
  9. let k2 = \Node.children
  10. t[keyPath: k1] // returns "false" works
  11. t[keyPath: k2] // returns "[:]" works
  12.  
  13. @objcMembers class MyController : NSObject {
  14. dynamic var tr: Node
  15. var kvo : NSKeyValueObservation!
  16. init(t: Node) {
  17. tr = t
  18. super.init()
  19. kvo = observe(\.tr) { object,change in
  20. print("\(object) \(change)")
  21. }
  22. }
  23. }
  24.  
  25.  
  26. let x = MyController(t: t)
  27. x.tr = Node(title:"f",children:[:])
  28. x

这个错误

fatal error: Could not extract a String from KeyPath
Swift.ReferenceWritableKeyPath<__lldb_expr_3.MyController,
__lldb_expr_3.Node>: file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-900.0.45.6/src/swift/stdlib/public/SDK/Foundation/NSObject.swift,
line 85

另外,请看到此错误

error: Execution was interrupted,reason: EXC_BAD_INSTRUCTION
(code=EXC_I386_INVOP,subcode=0x0). The process has been left at the
point where it was interrupted,use “thread return -x” to return to
the state before expression evaluation.

是否有其他人能够得到这样的工作,或者这是我需要报告的错误

这里的错误是编译器让你说:
  1. @objcMembers class MyController : NSObject {
  2. dynamic var tr: Node
  3. // ...

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:

  1. class Node : NSObject {
  2.  
  3. let title: String
  4. let leaf: Bool
  5. var children: [String: Node] = [:]
  6.  
  7. init(title: String,leaf: Bool,children: [String: Node]) {
  8. self.title = title
  9. self.leaf = leaf
  10. self.children = children
  11. }
  12. }

(如果你再次看一下WWDC视频,你会看到他们观察的属性实际上是一个继承自NSObject的类的类型)

但是,在您给出的示例中,您并不真正需要KVO – 您可以将Node保留为结构,而是使用属性观察器:

  1. struct Node {
  2. let title: String
  3. let leaf: Bool
  4. var children: [String: Node] = [:]
  5. }
  6.  
  7. class MyController : NSObject {
  8.  
  9. var tr: Node {
  10. didSet {
  11. print("didChange: \(tr)")
  12. }
  13. }
  14.  
  15. init(t: Node) {
  16. tr = t
  17. }
  18. }
  19. let x = MyController(t: Node(title:"hello",children: [:]))
  20. x.tr = Node(title:"f",leaf: false,children: [:])
  21. // didChange: Node(title: "f",children: [:])

而且因为Node是一个值类型,didSet也会触发对其属性的任何更改:

  1. x.tr.children["foo"] = Node(title: "bar",children: [
  2. // "foo": kvc_in_playground.Node(title: "bar",children: [:])
  3. // ])

猜你在找的Swift相关文章