The last time Hackerfall tried to access this page, it returned a not found error. A cached version of the page is below, or click here to continue anyway

An Observable Pattern Implementation in Swift · Colin Drake

An Observable Pattern Implementation in Swift

October 01, 2015

Over the past few days, Ive been working a new Mac app in Swift as a part of Gumroads Small Product Lab challenge. This app contains a simple struct type, AppConfig, representing the applications editable configuration. What I needed to build was a view controller for the user to edit and update said values, and this is where I ran into trouble.

The normal pattern in the Objective-C world to implement this is to use Cocoa Bindings, an awesome feature implemented on top of KVO that allows you to automatically bind your (Mac) UI to instance variables in Interface Builder.

However, Cocoa Bindings will only work for types that are subclasses of NSObject. I felt that porting my AppConfig struct over to a class, let alone an NSObject subclass, conflicted with the fact that it was better represented as a value type, and I definitely didnt want to needlessly bring in the Objective-C runtime for this simple case.

Given that Ive been working on this app to both scratch an itch and to use Swift in a practical setting, I decided to write my own native Swift implementation of the Observable Pattern.

Protocols Everywhere

To begin with, I wanted to come up with a protocol that I could implement to satisfy my data binding woes. I decided on a subscribe/unsubscribe type model, passing in an owner/observer as the object to update a subscription off of.

protocol ObservableProtocol {
    typealias T
    var value: T { get set }
    func subscribe(observer: AnyObject,
                   block: (newValue: T, oldValue: T) -> ())
    func unsubscribe(observer: AnyObject)

Assuming we are in some type of object context with self, implementing the Observable protocol would allow code to be written somewhat like this:

let initial = 3
var v = initial
var obs = Observable(initial)

obs.subscribe(self) { (newValue, oldValue) in
    print("Object updated!")
    v = newValue

obs.value = 4  // Trigger update.
print(v)       // 4!

Perfect! Now to write it


Given that the Observable object has state/a lifecycle, I decided to make it a class:

public final class Observable<T>: ObservableProtocol {
    // ...

Well start out by defining a variable and a couple of handy types.

Our model of subscribers is observers, a variable array of ObserversEntry entries. Each entry is a tuple composed of a listening object and the block it expects to run upon the Observable firing. By passing in this listening object and associating it with the block to execute, we can easily look for it in the unsubscribe method to remove it.

typealias ObserverBlock = (newValue: T, oldValue: T) -> ()
typealias ObserversEntry = (observer: AnyObject, block: ObserverBlock)
private var observers: Array<ObserversEntry>

Now well need to implement an init for our class. The default initializer will simply take an initial value for the observable (declaration forthcoming). Given that were writing Swift here, well need to initialize our non-optional observers array as well.

init(_ value: T) {
    self.value = value
    observers = []

At this point, when we construct an Observable well have an initial value. This value is even assignable, but currently we dont have any way of telling the objects in our observers array that the value changed. To do this, well implement didSet for our value variable. All we need to do is loop through our listeners and call their associated blocks. Simple!

var value: T {
    didSet {
        observers.forEach { (entry: ObserversEntry) in
            // oldValue is an implicit parameter to didSet in Swift!
            let (_, block) = entry
            block(newValue: value, oldValue: oldValue)

Last but not least, the mechanism to notify observers is in place, but we have no way to update the observers array. Well implement subscribe and unsubscribe to package up and add/remove observer tuples into the internal array.

func subscribe(observer: AnyObject, block: ObserverBlock) {
    let entry: ObserversEntry = (observer: observer, block: block)

func unsubscribe(observer: AnyObject) {
    let filtered = observers.filter { entry in
        let (owner, _) = entry
        return owner !== observer

    observers = filtered

Thats all it takes!

Note: Please keep in mind that this is a simple, nave, implementation without any considerations for performance, etc.

Syntactic Sugar

While this works, I figured I could throw in just a little syntactic sugar to reduce the repetition of writing foo.value = <value>. I decided to override the << operator:

func <<<T>(observable: Observable<T>, value: T) {
    observable.value = value

Update: It appears Ive been (fairly!) called out here by none other than Chris Lattner (the designer of the Swift language) himself for overriding and repurposing the bit shift operator I cant say I disagree:

As such, if you use this code Id recommend defining the <~ operator instead, or something else similarly unique!


With the above code, you can now wire up Observable objects to UI elements and instance variables. Just what I needed! Heres an example NSViewController implementation with an editable port value:

/// A view controller supporting editing of the app's config.
class PreferencesViewController: NSViewController {
    // The model layer.
    var configuration: ApplicationConfiguration

    // The view and object supporting the "controller".
    @IBOutlet var portTextField: NSTextField!
    var port: Observable<Int>

    // ...

    // MARK: NSViewController
    override func viewDidLoad() {

        port.subscribe(self) { (port, _) in
            // Ignore the old value, but update config with the new.
            self.configuration.port = port

            // You can trigger anything from here! Save to disk, etc...
            // Keeps action/UI code clean.

        // ...
        // Assume `portTextFieldDidUpdate` is wired to be
        // called when portTextField's value updates.
        // ...

    // MARK: Helpers
    func portTextFieldDidUpdate(value: Int) {
        port << value

Download this as an Xcode Playground.

Continue reading on