Skip to content

Instantly share code, notes, and snippets.

@iThinker
Created January 8, 2017 16:47
Show Gist options
  • Save iThinker/9fac8445c47c3d6abebe417cacddf541 to your computer and use it in GitHub Desktop.
Save iThinker/9fac8445c47c3d6abebe417cacddf541 to your computer and use it in GitHub Desktop.
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