Created
November 1, 2016 14:25
-
-
Save iThinker/aab85b16e0179b483e50ed4132634621 to your computer and use it in GitHub Desktop.
Observable V4
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
// | |
// 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