Created
December 22, 2017 17:49
-
-
Save dsxsxsxs/dd00e805c7ad13e4c24c4ca28a8b0d06 to your computer and use it in GitHub Desktop.
Super simple EventEmitter with disposebag
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
// | |
// EventEmitter.swift | |
// dsxs | |
// | |
// Created by dsxs on 2017/7/28. | |
// Copyright © 2017年 dsxs. All rights reserved. | |
// | |
import Foundation | |
struct Weak<T: AnyObject> { | |
weak var value : T? | |
init (_ value: T) { | |
self.value = value | |
} | |
} | |
public class EventListenerBag<E:Hashable, T:Any>:NSObject{ | |
var listeners:[Weak<EventListener<E, T>>] = [] | |
deinit { | |
for l in listeners{ | |
l.value?.emitter?.off(listener: l.value) | |
} | |
} | |
} | |
public class EventListener<E:Hashable, T:Any>:NSObject{ | |
public typealias Handler = (T) -> Void | |
public typealias Bag = EventListenerBag<E, T> | |
public typealias Emitter = EventEmitter<E, T> | |
var event:E! | |
var fn: Handler! | |
weak var emitter: Emitter! | |
public init(_ fn:Handler!){ | |
self.fn = fn | |
} | |
public func addTo(_ bag:Bag!) { | |
bag.listeners.append(Weak<EventListener<E, T>>(self)) | |
} | |
} | |
public class EventEmitter<E:Hashable, T:Any>:NSObject{ | |
public typealias Handler = (T) -> Void | |
public typealias Listener = EventListener<E, T> | |
var events = [E: [Listener]]() | |
@discardableResult | |
public func on(_ event:E, listener: Listener)->Listener{ | |
if events[event] == nil{ | |
events[event] = [] | |
} | |
listener.event = event | |
listener.emitter = self | |
events[event]?.append(listener) | |
return listener | |
} | |
@discardableResult | |
public func once(_ event:E, listener: Listener)->Listener{ | |
if events[event] == nil{ | |
events[event] = [] | |
} | |
let onceListener = Listener(nil) | |
let target = listener.fn | |
let fn:Handler = {[weak onceListener, weak self] obj in | |
target?(obj) | |
if onceListener != nil{ | |
self?.off(event, listener: onceListener) | |
} | |
} | |
onceListener.event = event | |
onceListener.fn = fn | |
onceListener.emitter = self | |
events[event]?.append(onceListener) | |
return onceListener | |
} | |
public func off(_ event:E, listener: Listener! = nil) { | |
if let listeners = events[event]{ | |
if listener == nil{ | |
events.removeValue(forKey: event) | |
}else if let index = listeners.index(of:listener) { | |
events[event]?.remove(at: index) | |
} | |
} | |
} | |
public func off(listener: Listener! = nil) { | |
if let event = listener.event{ | |
off(event, listener: listener) | |
} | |
} | |
@discardableResult | |
public func emit(_ event:E, object: T)->Bool { | |
if let handlers = events[event], handlers.count > 0{ | |
for handler in handlers{ | |
handler.fn(object) | |
} | |
return true | |
} | |
return false | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment