Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Key-Value Observing in Swift 4

I have the following code in my Swift 4 project.

class DishesTableViewController : UITableViewController {


    private var token :NSKeyValueObservation?

    @objc dynamic private(set) var dishes :[Dish] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        // configure the observation
        token = self.observe(\.dishes) { object, change in

            // change is always nil
            print(object)
            print(change)
        }

        updateTableView()
    }

Whenever the dishes array is changed, the observation is triggered. But my question is how can I get the actual changes that happened, that is, how can I access the actual Dish object that triggered the change?

like image 267
john doe Avatar asked Sep 28 '17 19:09

john doe


People also ask

Where is KVO used in Swift?

KVO, which stands for Key-Value Observing, is one of the techniques for observing the program state changes available in Objective-C and Swift. The concept is simple: when we have an object with some instance variables, KVO allows other objects to establish surveillance on changes for any of those instance variables.

Can you explain KVO?

Key-value observing is a mechanism that enables an object to be notified directly when a property of another object changes. It is a mode of communication between objects in applications designed in conformance with the Model-View-Controller design pattern.

What is KVO and KVC in Swift?

KVO and KVC or Key-Value Observing and Key-Value Coding are mechanisms originally built and provided by Objective-C that allows us to locate and interact with the underlying properties of a class that inherits NSObject at runtime.

What framework is KVO key-value observing a part of?

Key-Value Observing, KVO for short, is an important concept of the Cocoa API. It allows objects to be notified when the state of another object changes.


1 Answers

I think the reason change is coming up with nil is because you haven't specified options.

Rewrite as follows:

override func viewDidLoad() {
    super.viewDidLoad()

    // configure the observation
    token = self.observe(\.dishes, options: [.new,.old]) { object, change in

        print(object)
        let set1 = Set(change.newArray!)
        let set2 = Set(change.oldArray!)

        let filter = Array(set1.subtract(set2))
        print(filter)

    }

    updateTableView()
}

Note that I have done a bit of guesswork here about your Dish object. I am assuming you have made it conform to the Equatable protocol, and this is a necessary step for the solution to work.

UPDATE: This requirement has now been reflected in the official Apple documentation here.

If you don't need to know how a property has changed, omit the options parameter. Omitting the options parameter forgoes storing the new and old property values, which causes the oldValue and newValue properties to be nil.

like image 77
Pranav Kasetti Avatar answered Sep 28 '22 07:09

Pranav Kasetti