fireblade-ecs/Sources/FirebladeECS/EventHub.swift

81 lines
2.2 KiB
Swift

//
// EventHub.swift
// FirebladeECS
//
// Created by Christian Treffs on 09.10.17.
//
public protocol EventHub: class {
func subscribe<E: Event>(classRef eventHandlerRefUnowned: EventHandler, eventHandler: @escaping (E) -> Void)
func unsubscribe<E: Event>(classRef eventHandlerRefUnowned: EventHandler, eventHandler: @escaping (E) -> Void)
weak var sniffer: EventSniffer? { get set }
}
public class DefaultEventHub: EventHub, EventDispatcher {
public var sniffer: EventSniffer?
public init() { }
private var listeners: [UET: ContiguousArray<EventHandlerRef>] = [:]
private func typeEvent<E: Event>(opaqueEvent: Event, eventHandler: @escaping (E) -> Void ) {
guard let typedEvent: E = opaqueEvent as? E else {
fatalError() // TODO: meaningful message
}
eventHandler(typedEvent)
}
private func push(listener newListener: EventHandlerRef, `for` uet: UET) {
if listeners[uet] == nil {
listeners[uet] = []
listeners.reserveCapacity(1)
}
listeners[uet]?.append(newListener)
}
}
// MARK: - event center
extension DefaultEventHub {
final public func subscribe<E: Event>(classRef unownedListenerRef: EventHandler, eventHandler handler: @escaping (E) -> Void) {
let eventListener: EventHandlerRef = EventHandlerRef(eventHandlerClassRefUnowned: unownedListenerRef,
eventHandler: { self.typeEvent(opaqueEvent: $0, eventHandler: handler) })
push(listener: eventListener, for: E.uet)
sniffer?.subscriber(subsribed: E.uet)
}
final public func unsubscribe<E: Event>(classRef listenerRef: EventHandler, eventHandler handler: @escaping (E) -> Void) {
let uet: UET = E.uet
if let removeIdx: Int = listeners[uet]?.index(is: listenerRef) {
let removed = listeners[uet]?.remove(at: removeIdx)
assert(removed != nil)
sniffer?.subscriber(unsubsribed: uet)
}
}
}
// MARK: - event dispatcher delegate
extension DefaultEventHub {
final public func dispatch<E: Event>(_ event: E) {
let uet: UET = E.uet
listeners[uet]?.forEach {
$0.eventHandler(event)
}
sniffer?.dispatched(event: event)
}
}
// MARK: - event dumper
public protocol EventSniffer: class {
func subscriber(subsribed to: UET)
func subscriber(unsubsribed from: UET)
func dispatched<E: Event>(event: E)
}