I'm reading Head First Design Patterns and I'm trying to replicate the Design Patterns in a Swift Playground. I'm trying to get the Observer pattern working as per the book. My current source is as follows:
protocol Subject {
func register(observer: Observer)
func remove(observer: Observer)
func notifyObservers()
}
protocol Observer {
func update(temperature: Double, humidity: Double, pressure: Double)
}
protocol DisplayElement {
func display()
}
class WeatherData: Subject {
var observers: [Observer]
var temperature: Double!
var humidity: Double!
var pressure: Double!
init() {
observers = []
}
func register(observer: Observer) {
observers.append(observer)
}
func remove(observer: Observer) {
}
func notifyObservers() {
for obs: Observer in observers {
obs.update(temperature: temperature, humidity: humidity, pressure: pressure)
}
}
}
What I need to do is to implement the removeObserver method. The snippet that I need to implement is something as:
func remove(observer: Observer) {
let obs: Observer = observers.index(where: { (aObserver) -> Bool in
return aObserver == observer
})
}
However this is not allowing me to continue because of a compilation error:
Cannot convert value of type '(OptionalNilComparisonType) -> Bool' to expected argument type '() -> Bool'
Is it even possible to achieve this and what am I doing wrong?
Arbitrary objects are can not be tested for equality. There are many kinds of objects which full equality is difficult or even impossible to determine in Swift (and generally speaking in most popular languages; Swift just addresses this problem more explicitly than many other languages do). There are lots of ways to address this, but in your case you really likely mean that the observer is some specific instance of a class, a reference type, rather than a value. The number 4 is probably not allowed to be an observer, for instance. That's something that can happen in Swift, so you need to tell Swift that it isn't legal here because 4 is a value, not a reference.
OK, enough background. How do you do it? Well, first, say Observers have to be classes (i.e. reference types).
And now, you can say "if this object is exactly the same object as the observer" which is completely different than "if this thing is equal to the observer:"
Note the use of
===
here rather then==
.There are lots of other ways to attack this general problem, but this is the way that best matches the Observer pattern.