Skip to content

Instantly share code, notes, and snippets.

@iThinker
Created November 1, 2016 14:25
Show Gist options
  • Save iThinker/aab85b16e0179b483e50ed4132634621 to your computer and use it in GitHub Desktop.
Save iThinker/aab85b16e0179b483e50ed4132634621 to your computer and use it in GitHub Desktop.
Observable V4
//
// Observable.swift
// Geotification
//
// Created by Roman Temchenko on 2016-10-29.
// Copyright © 2016 Temkos. All rights reserved.
//
import Foundation
class ObserverStorage {
static let shared = ObserverStorage()
private var observablesMap: NSMapTable<AnyObject, AnyObject> = NSMapTable.weakToStrongObjects()
private func subscriptionsMap(forObservable observable: AnyObject) -> NSMapTable<AnyObject, AnyObject> {
var subscriptionsMap = self.observablesMap.object(forKey: observable) as? NSMapTable<AnyObject, AnyObject>
if subscriptionsMap == nil {
subscriptionsMap = NSMapTable.weakToStrongObjects()
self.observablesMap.setObject(subscriptionsMap, forKey: observable)
}
return subscriptionsMap!
}
func addObserver(_ observer: AnyObject, subscription: AnyObject, observable: AnyObject) -> Void {
let subscriptionsMap = self.subscriptionsMap(forObservable: observable)
subscriptionsMap.setObject(subscription, forKey: observer)
}
func removeObserver(_ observer: AnyObject, observable: AnyObject) -> Void {
let subscriptionsMap = self.subscriptionsMap(forObservable: observable)
subscriptionsMap.removeObject(forKey: observer)
}
func subscriptionsforObservable(_ observable: AnyObject) -> [Any] {
let sub = self.subscriptionsMap(forObservable: observable)
return sub.objectEnumerator()?.allObjects ?? []
}
}
protocol Observable: class {
associatedtype ObservableAction
typealias SubscriptionBlock = (ObservableAction) -> Void
func notifyObservers(_ action: ObservableAction) -> Void
func addObserver(_ observer: AnyObject, subscription: @escaping SubscriptionBlock) -> Void
func removeObserver(_ observer: AnyObject) -> Void
}
extension Observable {
func notifyObservers(_ action: ObservableAction) -> Void {
let subscriptions = ObserverStorage.shared.subscriptionsforObservable(self) as! [SubscriptionBlock]
for subscription in subscriptions {
subscription(action)
}
}
func addObserver(_ observer: AnyObject, subscription: @escaping SubscriptionBlock) -> Void {
ObserverStorage.shared.addObserver(observer, subscription: subscription as AnyObject, observable: self)
}
func removeObserver(_ observer: AnyObject) -> Void {
ObserverStorage.shared.removeObserver(observer, observable: self)
}
}
enum TestObservableActions {
case testAction
}
class TestObservable: Observable {
typealias ObservableAction = TestObservableActions
func testFunc() -> Void {
self.notifyObservers(.testAction)
}
}
class TestObserver {
internal func observe(_ action: TestObservableActions) {
print("Action: \(action)")
}
deinit {
print("Deinit")
}
}
func test() -> Void {
let testObservable = TestObservable()
let testObserver = TestObserver()
testObservable.addObserver(testObserver, subscription: {
[weak testObserver]
action in
testObserver?.observe(action)
})
testObservable.testFunc()
print("Test Complete");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment