Observer Design Pattern in Swift


Greetings, traveler!

We continue to discuss Design Patterns. In this article, we will analyze the Observer Pattern. You have likely encountered this pattern multiple times in your work. Many tools based on this pattern, such as Notification Center and KVO, as well as well-known reactive frameworks like RxSwift, are built on its foundation.

The Observer is a design pattern that enables you to define a mechanism for notifying multiple objects when an event occurs on the object they are observing.

Example of usage

Let’s dive into some practical examples to better understand the Observer Pattern’s purpose and usage. We’ll start with a simple yet illuminating example that will set the stage for more complex scenarios.

So, let’s start with the interface.

protocol ObserverProtocol: AnyObject {
    func update<T>(_ value: T)
}

Now, let’s move on to implementation.


final class StringObserver: ObserverProtocol {
    
    func update<T>(_ value: T) {
        guard let value = value as? String else {
            return
        }
        
        print(value)
    }
    
}

This class expects a string to come as the value. In this case, it will output this value to the console.

Now, let’s create a ViewModel. It will have a reference to the Observer, which it will notify every time the value of a specified property changes.

final class ViewModel {
    
    private weak var observer: ObserverProtocol?
    private var value: String = "" {
        didSet {
            observer?.update(value)
        }
    }
    
    init(observer: ObserverProtocol) {
        self.observer = observer
    }
    
    func preloadData() {
        value = "New Value"
    }
    
}

Now, we can use these objects.

let observer = StringObserver()
let viewModel = ViewModel(observer: observer)

viewModel.preloadData()

Conclusion

And that’s all we can say about the basics of the Observer pattern. This pattern helps to subscribe objects to certain events. For example, you can dynamically update the user interface depending on the model’s state. Of course, many options exist for a more flexible and interesting implementation. You have probably already used some of them. However, to create your own implementation, it’s important to understand the fundamentals of the concept. That’s why we’ve gathered today. Now, let’s move on to the next pattern — the State pattern.