Swift — Observers

Adi Mizrahi
4 min readAug 22, 2021

--

During my work on numerous apps, I’ve run into the need of detecting when my app goes from the background to foreground and vice versa.

Sometimes i want to save a state, or an image, or just change a text when the user decides to move the app into the background, on the other side, when the user moves the app into foreground (while it was in the background) I want to show some kind of view or notify the user that something is happening.

To achieve that kind of behaviour the great minds of Apple gave us the Observer.
The Observer is a pattern in Swift, and it’s implemented in iOS with KVO (Key-Value observing).
An Observer is an object that notifies when the state of another object changed.
An Observer can be registered and deregistered by a subject (UIViewController for example), it’s important to register them so they can work, and let’s not forget to deregister to prevent memory leaks.

An object needs to subscribe to an Observer to let the observer know it wants to be notified when changes take place.

What is KVO?

Before we dive into types and examples for observers i want to show and explain what is KVO (Key-Value observing).
In general term KVO is a programming pattern, we use it to notify objects about changes in their properties.
Important: you can only use KVO in objects that inherits NSObject.
Let’s take a look at KVO example:

Here we define a new class Dog (important , the Dog class inherits NSObject so it can use the KVO pattern), the object has a name with the word dynamic, then we create a new object myDog from the class Dog.
Let’s continue so we can see how we can use the KVO pattern:

We define an observe on our new myDog object, and print the new name, which means , when someones changes the name property for myDog the console will the change.
To test this we can do the following:

One we run the following code the console will print the following:

My new name is: Snowy

Foreground

To be able to detect when the app comes from the background into the foreground we need to register the following observer:

As we can see in the snippet above, we’re retrieving the default state of the NotificationCenter and adding an Observer.
forName: field here is important, the UIApplication.willEnterForegroundNotification is a saved Swift phrase and is there to tell the system we would like to listen when the app goes to foreground.
object: field defines the object that sent the notification to this Observer block.
queue: field defines the operation queue where the code in the closure will run, if the queue is set to nil the code will run synchronously in the thread that posted this Observer.

Another way to add this observer is:

selector: the block of code that will run once the notification for this Observer is sent.
The only difference in this snippet is that instead of having a closure and defining what to do as part of the Observer declaration, we’re giving a selector with our function, this selector is executed when the app enters foreground.

Background

As i mentioned before, sometimes we want to understand when the user moves the app to the background (by clicking the home button for example or swiping the screen up in notch devices).

The following code shows how to add the observer for listening when the app goes to the background.
Important: this is the exact same declaration as the foreground observer I mentioned before, the only difference is the forName: field.

Here is another way to declare a background Observer.

After registering our observers, they are ready to be used, they are currently listening and will let us know when the expected behaviour will take place (app moves to foreground or background).
Like I wrote at the beginning we must not forget to deregister the observers when we’re done using them, keeping the observers alive can cause memory leaks or other unexpected behaviour.

The following code deregister all observers from the current object:

The following code removes all the observers registered for the current object.

But what if we want to remove a specific observer, how do we do that?
First, we need to register the observer a bit differently and keep a reference to it.

We created an observer of type NSObjectProtocol and registered the foreground Observer into it.
So now we hold reference to the Observer, let’s see how can we release this Observer only, the following code shows how we can deregister a single Observer

In the code above we can see how we can release a single Observer and not all registered Observers in that object.
A small suggestion, i usually release my Observer in the deinit function, this function is called when the object is released and not needed anymore.

Conclusion

There are many other observer types you can register into your app, in the following article I just showed two important and useful examples, you can even register your own Observer.
It’s important to remember to deregister the observer when you’re done with it to prevent unexpected behaviour and memory leaks.
For further reading click here

--

--