Skip to content

Instantly share code, notes, and snippets.

@ChristianVinterly
Last active July 12, 2017 15:15
Show Gist options
  • Save ChristianVinterly/d8952a2e5479a180a44bc311385f651e to your computer and use it in GitHub Desktop.
Save ChristianVinterly/d8952a2e5479a180a44bc311385f651e to your computer and use it in GitHub Desktop.
Alternative observer pattern in swift, with playground example
//: Playground - noun: a place where people can play
import UIKit
private class Weak: Hashable {
let hashValue: Int
weak var value: AnyObject?
init(value: AnyObject) {
self.value = value
self.hashValue = ObjectIdentifier(value).hashValue
}
static func ==(lhs: Weak, rhs: Weak) -> Bool {
return lhs.hashValue == rhs.hashValue
}
}
class Provider<ObserverType> {
private var weakObservers = Set<Weak>()
private var observers: [ObserverType] {
weakObservers = Set(weakObservers.filter{ $0.value != nil })
return weakObservers.flatMap{ $0.value as? ObserverType }
}
func add(observer: ObserverType) {
let weak = Weak(value: observer as AnyObject)
guard weak.value != nil else { return assertionFailure("ObserverType must be class bound") }
weakObservers.insert(weak)
}
func remove(observer: ObserverType) {
let weak = Weak(value: observer as AnyObject)
guard weak.value != nil else { return assertionFailure("ObserverType must be class bound") }
weakObservers.remove(weak)
}
func post(block: (ObserverType) -> Void) {
observers.forEach(block)
}
}
// Example usage:
struct User {
let name: String
}
protocol UserObserver: class {
func didUpdate(user: User, in provider: UserProvider)
}
class UserProvider: Provider<UserObserver> {
func updateUser() {
//Update user as needed, then push update to observers:
let user = User(name: "John Doe")
post{ $0.didUpdate(user: user, in: self) }
}
}
class PresenterA: UserObserver {
func didUpdate(user: User, in provider: UserProvider) {
print("A: \(user.name)")
}
}
class PresenterB: UserObserver {
func didUpdate(user: User, in provider: UserProvider) {
print("B: \(user.name)")
}
}
let provider = UserProvider()
let presenterA = PresenterA()
let presenterB = PresenterB()
provider.add(observer: presenterA)
provider.add(observer: presenterB)
print("updating user")
provider.updateUser()
provider.remove(observer: presenterA)
print("updating user")
provider.updateUser()
/*
Output:
updating user
A: John Doe
B: John Doe
updating user
B: John Doe
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment