2016-06-30 13 views
3

Ich versuche herauszufinden, wie die [NSKeyValueChangeKey : AnyObject] Änderung Wörterbuch Parameter in func observeValue(forKeyPath... auszuwerten. Ich habe den folgenden Code in einem Spielplatz und die Art, wie ich das Change-Wörterbuch auswerte ich immer am Ende denke, die Änderung ist ein NSKeyValueChange.setting (was definitiv falsch ist).KVO und Swift 3.0: Wie kann das Änderungswörterbuch ausgewertet werden?

Was ist der richtige Weg, um das Änderungswörterbuch auszuwerten?

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() 
+0

Geht man durch die [Dokumentation] (https://developer.apple.com/reference/foundation/nskeyvaluechange), habe ich den Eindruck, dass 'insert',' removal' und 'replacement' nur für Core Data-Änderungen gelten. –

+1

Das ist nicht wahr. Es stellt sich heraus, dass für die Überwachung von Änderungen an einem Array eine kvo-konforme Version benötigt wird, die mit 'let kvoArray = self.mutableArrayValue (forKey: MediaItems ')' erhalten werden kann. Alle Änderungen an' kvoArray' lösen die entsprechenden KVO-Nachrichten aus. – RobertJoseph

Antwort

0

Da die ursprünglichen Fragesteller in seinem Kommentar darauf hingewiesen, wird der folgende Code des erwartete Ergebnis geben:

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()