Last active
July 12, 2017 15:15
-
-
Save ChristianVinterly/d8952a2e5479a180a44bc311385f651e to your computer and use it in GitHub Desktop.
Alternative observer pattern in swift, with playground example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: 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