Implementing the Observable class

We'll implement Observable as a generic class, as it should be able to wrap any kind of object:

class Observable<Type> {
typealias Observer = (Type) -> ()
typealias Token = NSObjectProtocol

private var observers = [(Token, Observer)]()

var value: Type {
didSet {
notify()
}
}

init(_ value: Type) {
self.value = value
}

@discardableResult
func bind(_ observer: @escaping Observer) -> Token {
defer { observer(value) }
let obj = NSObject()
observers.append((obj, observer))
return obj
}

func unbind(_ token: Token) {
observers.removeAll { $0.0.isEqual(token) }
}

private func notify() {
observers.forEach { (_, observer) in
observer(value)
}
}
}

We can demonstrate the capabilities of this Observer<Type> object through the following snippet:

let observable = Observable("")
let token0 = observable.bind {
print("Changed 0: \($0)")
}
observable.value = "OK"
let token1 = observable.bind {
print("Changed 1: \($0)")
}
observable.unbind(token1)
observable.value = "NOK"

// Output:
Changed 0: // initial binding
Changed 0: OK // the value is set to OK, notifying
Changed 1: OK // initial binding of second observer
Changed 0: NOK // The value is set to NOK, notifying

With the Observable<Type> class, we are able to subscribe to changes occurring at the model layer. The next step is to bind the observable to UIKit elements, which can have their values change.