Created
November 4, 2023 11:34
-
-
Save calvingit/b9d899a2d6a966f7a9296ad4a65a9695 to your computer and use it in GitHub Desktop.
广播事件分发器
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
import Foundation | |
// 事件 | |
@objcMembers | |
class EPEvent: NSObject { | |
/// 事件 id,唯一 | |
private(set) var id: String = "" | |
/// 对象参数 | |
private(set) var object: Any? | |
/// 序列化参数 | |
private(set) var params: [String: Any]? | |
private override init() { | |
super.init() | |
} | |
convenience init(id: String, object: Any? = nil, params: [String: Any]? = nil) { | |
self.init() | |
self.id = id | |
self.object = object | |
self.params = params | |
} | |
/// 以下方法暴露给 Objective-C | |
@objc(eventWithId:) | |
static func event(_ id: String) -> EPEvent { | |
EPEvent(id: id, params: nil) | |
} | |
@objc(eventWithId:params:) | |
static func event(_ id: String, params: [String: Any]?) -> EPEvent { | |
EPEvent(id: id, params: params) | |
} | |
@objc(eventWithId:object:) | |
static func event(_ id: String, object: Any?) -> EPEvent { | |
EPEvent(id: id, object: object) | |
} | |
} | |
/// EPEventDisposable 对象释放时取消订阅事件,由 subscribeSingleEvent(_:completion:) 方法返回 | |
@objcMembers | |
class EPEventDisposable: NSObject { | |
private var disposeAction: (() -> Void)? | |
init(disposeAction: @escaping () -> Void) { | |
self.disposeAction = disposeAction | |
} | |
private override init() { | |
super.init() | |
} | |
deinit { | |
disposeAction?() | |
} | |
} | |
// 事件订阅协议 | |
@objc protocol EPEventSubscriber { | |
func receiveEvent(_ event: EPEvent) | |
} | |
// 事件分发器 | |
@objc class EventPublisher: NSObject { | |
@objc static let shared = EventPublisher() | |
private var subscribers: [EPEventSubscriber] = [] | |
private var singleSubscribers: [String: (EPEvent) -> Void] = [:] | |
private let eventQueue = DispatchQueue(label: "com.EventPublisher.eventQueue", attributes: .concurrent) | |
private override init() { | |
super.init() | |
} | |
// 订阅所有事件 | |
@objc func subscribe(_ subscriber: EPEventSubscriber) { | |
eventQueue.async(flags: .barrier) { | |
self.subscribers.append(subscriber) | |
print("\(self.subscribers)") | |
} | |
} | |
// 订阅单个事件 | |
@objc func subscribeSingleEvent(_ eventId: String, completion: @escaping (EPEvent) -> Void) -> EPEventDisposable { | |
let disposable = EPEventDisposable { [weak self] in | |
self?.unsubscribeSingleEvent(eventId) | |
} | |
eventQueue.async(flags: .barrier) { | |
self.singleSubscribers[eventId] = completion | |
} | |
return disposable | |
} | |
// 取消订阅单个事件 | |
private func unsubscribeSingleEvent(_ eventId: String) { | |
eventQueue.async(flags: .barrier) { | |
self.singleSubscribers.removeValue(forKey: eventId) | |
} | |
} | |
// Method to unsubscribe from events | |
@objc func unsubscribe(_ subscriber: EPEventSubscriber) { | |
eventQueue.async(flags: .barrier) { | |
self.subscribers.removeAll { $0 === subscriber } | |
print("\(self.subscribers)") | |
} | |
} | |
// 发布事件给所有订阅者 | |
@objc func publish(_ event: EPEvent) { | |
eventQueue.async { | |
for subscriber in self.subscribers { | |
NSLog("\(subscriber)") | |
DispatchQueue.main.async { | |
subscriber.receiveEvent(event) | |
} | |
} | |
if let completion = self.singleSubscribers[event.id] { | |
DispatchQueue.main.async { | |
completion(event) | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment