【问题标题】:KVO and Swift 3.0: How to evaluate the change dictionary?KVO 和 Swift 3.0:如何评估变更字典?
【发布时间】:2016-06-30 13:53:31
【问题描述】:

我试图弄清楚如何评估func observeValue(forKeyPath... 中的[NSKeyValueChangeKey : AnyObject] 更改字典参数。我在操场上有以下代码以及我评估更改字典的方式我总是最终认为更改是 NSKeyValueChange.setting (这绝对是错误的)。

评估变化字典的正确方法是什么?

import Foundation

class KVOTester: NSObject {

  dynamic var items = [Int]()   // Observe via KVO

  override init() {
    super.init()

    self.addObserver(self, forKeyPath: #keyPath(KVOTester.items), options: [], context: nil)
  }

  deinit {
    self.removeObserver(self, forKeyPath: #keyPath(KVOTester.items))
  }

  func exerciseKVO() {
    self.items = [Int]()      // NSKeyValueChange.setting
    self.items.append(1)      // NSKeyValueChange.insertion
    self.items[0] = 2         // NSKeyValueChange.replacement
    self.items.remove(at: 0)  // NSKeyValueChange.removal
  }

  override func observeValue(forKeyPath keyPath: String?, of object: AnyObject?, change: [NSKeyValueChangeKey : AnyObject]?, context: UnsafeMutablePointer<Void>?) {

    // We are only interested in changes to our items array
    guard keyPath == "items" else { return }

    // #1: object is the KVOTester instance - why isn't it the items array?

    // #2 I don't understand how to use the change dictionary to determine what type of change occurred. The following
    //    is wrong - it *always* prints "Setting".
    if let changeKindValue = change?[.kindKey] as? UInt, changeType = NSKeyValueChange(rawValue: changeKindValue) {
      switch changeType {
      case .setting:
        print("Setting")
        break
      case .insertion:
        print("Insertion")
        break
      case .removal:
        print("Removal")
        break
      case .replacement:
        print("Replacement")
        break
      }
    }
  }
}

let kvoTester = KVOTester()
kvoTester.exerciseKVO()

【问题讨论】:

  • 通过documentation,我的印象是insertionremovalreplacement仅适用于Core Data更改
  • 这不是真的。事实证明,要监视对阵列的更改,您需要一个兼容 kvo 的版本,可以使用let kvoArray = self.mutableArrayValue(forKey: MediaItems") 获得。对 kvoArray 所做的任何更改都会触发相应的 KVO 消息。

标签: swift key-value-observing swift3


【解决方案1】:

正如原提问者在评论中指出的那样,以下代码将给出预期的结果:

import Foundation

class KVOTester: NSObject {

    dynamic var items = [Int]() // Observe via KVO

    override init() {
        super.init()

        self.addObserver(self, forKeyPath: #keyPath(KVOTester.items), options: [], context: nil)
    }

    deinit {
        self.removeObserver(self, forKeyPath: #keyPath(KVOTester.items))
    }

    func exerciseKVO() {

        let kvoArray = self.mutableArrayValue(forKey: #keyPath(KVOTester.items))

        items = [Int]()                         // NSKeyValueChange.setting
        kvoArray.add(1)                         // NSKeyValueChange.insertion
        kvoArray.replaceObject(at: 0, with: 2)  // NSKeyValueChange.replacement
        kvoArray.removeObject(at: 0)            // NSKeyValueChange.removal
    }

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

        // We are only interested in changes to our items array
        guard keyPath == "items" else { return }

        if  let changeKindValue = change?[.kindKey] as? UInt,
            let changeType = NSKeyValueChange(rawValue: changeKindValue) {

            switch changeType {
            case .setting:
                print("Setting")
                break
            case .insertion:
                print("Insertion")
                break
            case .removal:
                print("Removal")
                break
            case .replacement:
                print("Replacement")
                break
            }
        }
    }
}

let kvoTester = KVOTester()
kvoTester.exerciseKVO()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-12
    • 2018-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多