Skip to content

Instantly share code, notes, and snippets.

@iThinker
Created November 1, 2016 01:30
Show Gist options
  • Save iThinker/6b1f07a00b059e9f8f5f5d78f914b5b2 to your computer and use it in GitHub Desktop.
Save iThinker/6b1f07a00b059e9f8f5f5d78f914b5b2 to your computer and use it in GitHub Desktop.
Observable V3
import Foundation
class ObserverStorage {
static let shared = ObserverStorage()
private var observablesMap: NSMapTable<AnyObject, AnyObject> = NSMapTable.weakToStrongObjects()
private func subscriptionsMap<T: Observable>(forObservable observable: T) -> NSMapTable<AnyObject, AnyObject> {
var subscriptionsMap = self.observablesMap.object(forKey: observable) as? NSMapTable<AnyObject, AnyObject>
if subscriptionsMap == nil {
subscriptionsMap = NSMapTable.weakToWeakObjects()
self.observablesMap.setObject(subscriptionsMap, forKey: observable)
}
return subscriptionsMap!
}
func addObserver<U, T: Observable>(_ observer: AnyObject, subscription: U, observable: T) -> Void {
let subscriptionsMap = self.subscriptionsMap(forObservable: observable)
subscriptionsMap.setObject(subscription as AnyObject, forKey: observer)
}
func removeObserver<T: Observable>(_ observer: AnyObject, observable: T) -> Void {
let subscriptionsMap = self.subscriptionsMap(forObservable: observable)
subscriptionsMap.removeObject(forKey: observer)
}
func subscriptions<U: Observable, T>(forObservable observable: U) -> [T] {
return self.subscriptionsMap(forObservable: observable).objectEnumerator()?.allObjects as! [T]
}
}
protocol Observable: class {
associatedtype ObservableAction
typealias SubscriptionBlock = (ObservableAction) -> Void
func notifyObservers(_ action: ObservableAction) -> Void
func addObserver(_ observer: AnyObject, subscription: SubscriptionBlock) -> Void
func removeObserver(_ observer: AnyObject) -> Void
}
extension Observable {
func notifyObservers(_ action: ObservableAction) -> Void {
let subscriptions: [SubscriptionBlock] = ObserverStorage.shared.subscriptions(forObservable: self)
for subscription in subscriptions {
subscription(action)
}
}
func addObserver(_ observer: AnyObject, subscription: SubscriptionBlock) -> Void {
ObserverStorage.shared.addObserver(observer, subscription: subscription, observable: self)
}
func removeObserver(_ observer: AnyObject) -> Void {
ObserverStorage.shared.removeObserver(observer, observable: self)
}
}
enum TestObservableActions {
case testAction
}
class TestObservable: Observable {
internal var subscriptions: NSMapTable<AnyObject, AnyObject> = NSMapTable.weakToWeakObjects()
typealias ObservableAction = TestObservableActions
func testFunc() -> Void {
self.notifyObservers(.testAction)
}
}
class TestObserver {
internal func observe(_ action: TestObservableActions) {
print("Action: \(action)")
}
}
func test() -> Void {
let testObservable = TestObservable()
let testObserver = TestObserver()
testObservable.addObserver(testObserver, subscription: testObserver.observe)
testObservable.testFunc()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment