Skip to content

Instantly share code, notes, and snippets.

@lorenalexm

lorenalexm/Events.swift

Last active Mar 22, 2021
Embed
What would you like to do?
The work on porting the UnityMessenger (https://github.com/lorenalexm/UnityMessenger) from C# to Swift using Silver.
// MARK: Placeholder, replace with real types
public enum EventType {
case notSet
}
// MARK: Delegate type aliases
public typealias Callback = () -> ()
public typealias Callback<T> = (arg: T) -> ()
// MARK: Event exceptions
public class HandlerException: Exception {
/// Constructor to forward message to base Exception class
/// - parameter message: The message to be thrown with the exception
init(_ message: String) {
super.init(message)
}
}
public class BroadcastException: Exception {
/// Constructor to forward message to base Exception class
/// - parameter message: The message to be thrown with the exception
init(_ message: String) {
super.init(message)
}
}
static internal class EventsManager {
// MARK: Fields
static var eventTable: [EventType:Delegate] = [:]
// MARK: Class functions
/// Adds event KVP to the table if not already present
/// - parameter type: Key for the event
/// - parameter handler: Delegate response for the event
static func onAdding(_ type: EventType, handler: Delegate) {
if eventTable.keys.contains(type) == false {
_ = eventTable.updateValue(handler, forKey: type)
}
var delegate: Delegate = eventTable[type]
if delegate != nil && delegate.GetType() != handler.GetType() {
throw HandlerException("Attempting to add handler with inconsistent signatures for event type \(type).")
}
}
/// Removes event KVP from table if delegate is no longer assigned
/// - parameter type: Key for the event
/// - parameter handler: Delegate response for the event
static func onRemoved(_ type: EventType, handler: Delegate) {
var delegate: Delegate? = eventTable[type]
if delegate == nil {
_ = eventTable.removeValue(forKey: type)
}
}
/// Checks if the KVP exists within the table, throws a BroadcastException if not
/// - parameter type: Key for the event
static func onBroadcasting(type: EventType) {
if eventTable.keys.contains(type) == false {
throw BroadcastException("Broadcasting event \(type), but no listeners are found.")
}
}
/// Creates a new BroadcastException for signature mismatches
/// - parameter type: The EventType the broadcast was sent with
static public func signatureExceptionFor(_ type: EventType) -> BroadcastException {
BroadcastException("Broadcasting event \(type) but listeners have a different signature than the broadcaster.")
}
}
static public class Events {
// MARK: Fields
static private var eventTable: [EventType:Delegate] = EventsManager.eventTable
//MARK: Class functions
/// Adds the Callback handler to the event table
/// - parameter type: Event to which the handler will be added
/// - parameter handler: Handler to be called when event is received
public static func addHandler(type: EventType, handler: Callback) {
EventsManager.onAdding(type, handler: handler)
eventTable[type] += handler
}
/// Removes the Callback handler from the event table
/// - parameter type: Event from which the handler will be removed
/// - parameter handler: Handler to be called when event is received
public static func removeHandler(type: EventType, handler: Callback) {
eventTable[type] -= handler
EventsManager.onRemoved(type, handler: handler)
}
/// Broadcasts an event to all handlers
/// - parameter type: Event to broadcast
public static func broadcast(type: EventType) {
let callback: Callback = eventTable[type] as! Callback
if callback != nil {
callback()
} else {
throw EventsManager.signatureExceptionFor(type)
}
}
}
static public class Events<T> {
// MARK: Fields
static private var eventTable: [EventType:Delegate] = EventsManager.eventTable
// MARK: Class functions
/// Adds the Callback handler to the event table
/// - parameter type: Event to which the handler will be added
/// - parameter handler: Handler to be called when event is received
public static func addHandler(type: EventType, handler: Callback<T>) {
EventsManager.onAdding(type, handler: handler)
eventTable[type] += handler
}
/// Removes the Callback handler from the event table
/// - parameter type: Event from which the handler will be removed
/// - parameter handler: Handler to be called when event is received
public static func removeHandler(type: EventType, handler: Callback<T>) {
eventTable[type] -= handler
EventsManager.onRemoved(type, handler: handler)
}
/// Broadcasts an event to all handlers
/// - parameter type: Event to broadcast
/// - parameter argument: Argument to be passed along with the event
public static func broadcast(type: EventType, argument: T) {
let callback: Callback<T> = eventTable[type] as! Callback<T>
if callback != nil {
callback(argument)
} else {
throw EventsManager.signatureExceptionFor(type)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment