Skip to content

Instantly share code, notes, and snippets.

@OdNairy
Forked from ColinEberhardt/Swift Events
Created April 18, 2019 09:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OdNairy/974ccf6f6434f0f2b44a1a11bbbb3ab2 to your computer and use it in GitHub Desktop.
Save OdNairy/974ccf6f6434f0f2b44a1a11bbbb3ab2 to your computer and use it in GitHub Desktop.
An eventing mechanism for Swift
/// An object that has some tear-down logic
public protocol Disposable {
func dispose()
}
/// An event provides a mechanism for raising notifications, together with some
/// associated data. Multiple function handlers can be added, with each being invoked,
/// with the event data, when the event is raised.
public class Event<T> {
public typealias EventHandler = T -> ()
private var eventHandlers = [Invocable]()
public init() {
}
/// Raises the event, invoking all handlers
public func raise(data: T) {
for handler in self.eventHandlers {
handler.invoke(data)
}
}
/// Adds the given handler
public func addHandler<U: AnyObject>(target: U, handler: (U) -> EventHandler) -> Disposable {
let wrapper = EventHandlerWrapper(target: target, handler: handler, event: self)
eventHandlers.append(wrapper)
return wrapper
}
}
// MARK:- Private
// A protocol for a type that can be invoked
private protocol Invocable: class {
func invoke(data: Any)
}
// takes a reference to a handler, as a class method, allowing
// a weak reference to the owning type.
// see: http://oleb.net/blog/2014/07/swift-instance-methods-curried-functions/
private class EventHandlerWrapper<T: AnyObject, U> : Invocable, Disposable {
weak var target: T?
let handler: T -> U -> ()
let event: Event<U>
init(target: T?, handler: T -> U -> (), event: Event<U>){
self.target = target
self.handler = handler
self.event = event;
}
func invoke(data: Any) -> () {
if let t = target {
handler(t)(data as U)
}
}
func dispose() {
event.eventHandlers = event.eventHandlers.filter { $0 !== self }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment