Created
January 8, 2017 16:47
-
-
Save iThinker/9fac8445c47c3d6abebe417cacddf541 to your computer and use it in GitHub Desktop.
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
import Foundation | |
class AssociationsStorage { | |
class Associations { | |
private var storage: [AnyHashable: Any] = [:] | |
func setValue(_ value: Any, forKey key: AnyHashable) { | |
self.storage[key] = value | |
} | |
func removeValue(forKey key: AnyHashable) { | |
self.storage[key] = nil | |
} | |
func value(forKey key: AnyHashable) -> Any? { | |
return self.storage[key] | |
} | |
} | |
static let shared = AssociationsStorage() | |
private var associationsMap: NSMapTable<AnyObject, AnyObject> = NSMapTable.weakToStrongObjects() | |
func associations(for object: AnyObject) -> Associations { | |
if let associations = self.associationsMap.object(forKey: object) as? Associations { | |
return associations | |
} | |
else { | |
let associations = Associations() | |
self.associationsMap.setObject(associations, forKey: object) | |
return associations | |
} | |
} | |
} | |
func setAssociation<T>(_ association: T?, forKey key: AnyHashable, object: AnyObject) { | |
let associations = AssociationsStorage.shared.associations(for: object) | |
switch association { | |
case .some(let value): | |
associations.setValue(value, forKey: key) | |
break | |
case .none: | |
associations.removeValue(forKey: key) | |
break | |
} | |
} | |
func getAssociation<T>(forKey key: AnyHashable, object: AnyObject) -> T? { | |
let associations = AssociationsStorage.shared.associations(for: object) | |
return associations.value(forKey: key) as? T | |
} | |
protocol DomainEvent { | |
typealias Subscription = (Self) -> Void | |
static var notificationName: Notification.Name { get } | |
} | |
let DomainEventKey = "DomainEventKey" | |
extension DomainEvent { | |
static var notificationName: Notification.Name { | |
return Notification.Name(String(describing: self)) | |
} | |
static func subscribe(observer: AnyObject, queue: OperationQueue = OperationQueue.main, subscription: @escaping Subscription) { | |
let observationInfo = NotificationCenter.default.addObserver(forName: Self.notificationName, object: nil, queue: queue) { (notification) in | |
let domainEvent = notification.userInfo?[DomainEventKey] as! Self | |
subscription(domainEvent) | |
} | |
setAssociation(observationInfo, forKey: self.notificationName.rawValue, object: observer) | |
} | |
static func unsubscribe(observer: AnyObject) { | |
let observationInfo: NSObjectProtocol? = getAssociation(forKey: self.notificationName.rawValue, object: observer) | |
NotificationCenter.default.removeObserver(observationInfo as Any) | |
} | |
func post() { | |
NotificationCenter.default.post(name: Self.notificationName, object: nil, userInfo: [DomainEventKey: self]) | |
} | |
} | |
class ConcreteDomainEvent: DomainEvent { | |
var payload: String! | |
} | |
let testObserver = NSObject() | |
ConcreteDomainEvent.subscribe(observer: testObserver) { (event) in | |
print("") | |
print("event \(event.payload!)") | |
} | |
let event = ConcreteDomainEvent() | |
event.payload = "Hello" | |
event.post() | |
ConcreteDomainEvent.unsubscribe(observer: testObserver) | |
event.post() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment