Playing with Key-Value Observing (KVO) (Swift3)

Erica Millado
4 min readJan 19, 2017

--

This photo has nothing to do with this blog post, it’s just funny.

What is key-value observing? Just like the name suggests, it is a mechanism that allows one object to observe properties of another object.

What can be “observable”?

To be observable, it has to inherit from NSObject and it has to have dynamic properties. Being dynamic means that a property can be dynamically dispatched at runtime.

Does my observable object need to be a class? Can it be a struct or enum?

Observable properties must be classes (Objective-C types), so the Swifty types such as structs and enums are unable to be dynamically observed. Every class object defined in the Foundation framework conforms to the NSKeyValueObserving protocol.

What does an observer actually do?

When an object (i.e. a viewController) is added as an observer, it receives a notification when the property it’s observing is changed.

What’s an example of implementing a key-value observer?

So, let’s say I have a WKWebView object and that I want to observe one of its properties, estimatedProgress.

This WKWebView property is what I want to observe.

First, I need to add an observer that will receive notification of the estimatedProgress changing. Here, I make my ViewController the observer.

On line 21 above, I call the .addObserver method on seaWebView, an instance of a WKWebView. The .addObserver method has four parameters: observer, forKeyPath, options, and context.

observer = the object that is doing the listening (aka my ViewController, self)

forKeyPath = the property that I am observing (aka estimatedProgress). Note: this is a string literal. This KVO is an Objective-C mechanism so keys and key paths are strings. Be careful typing this bad boy in!

options = represents what types of information the observer receives. Types include .new (the new value of the property), .old (the old value of the property), .initial (the immediate value sent to the observer before the .addObserver method is even added), .prior (sends a notification BEFORE and AFTER any changes happen).

context = a notification message that contains arbitrary data passed back to the observer in the corresponding change notifications. I set this to nil above.

Second, I need to implement the observeValue( ) method.

Line 31 = I implement the observeValue method.

On line 31, I implement the observeValue method which takes in four parameters, keyPath, object, change, and context.

keyPath = the property that you are observing (aka estimatedProgress)

object = references the object that is being observed

change = the changes observed are stored in a dictionary of [NSKeyValueChangeKey:Any]? So, all the observed properties’ changes are kept in this dictionary.

context = This context is the same one that was added in the .addObserver method (here, it is nil)

In the observeValue method above, I check to that the keyPath being observed is the keyPath that I added to the observer and then I write a print statement that prints out the percentage of the estimated progress of the WKWebView as it loads.

Watch the video below (apologies for the slow loading simulator) to see it run.

Watch what this key-value observer code looks like when run!

Third, I need to remove this observer since the web view is fully loaded and I no longer need to observe its estimated progress. Each observer needs to be individually removed and if not removed, it could lead to a memory leaks!

Line 38 = removes the observer I added earlier.

Though Swift automatically deallocates instances when they are no longer needed, with key value observation, we need to do the clean up ourself.

I removed the observer on line 38 in the deinit closure.

For the record, there are two methods that explicitly remove observers:

  • removeObserver(_:forKeyPath:)
  • removeObserver(_:forKeyPath:context:)

There are many other ways to use key-value observation in XCode, but because it works only with classes, alternative ways of observing need to utilized with structs and enums. You should consider this when building your code.

Leave a comment below and let me know how you use key-value observation.

You can find my code here.

I leave you with a beautiful photo of sea life.

Resources:

Key-value Observing Programming Guide — Apple Documentation

--

--