Event Bus 与观察者模式在 Swift 中的实现(iOS/macOS)
在 iOS 和 macOS 开发中,经常需要组织应用程序组件之间的松耦合交互。观察者模式及其通过事件总线(Event Bus)的实现,是创建灵活且可扩展架构的强大工具。在本文中,我们将探讨如何在 Swift 中实现 Event Bus,将其与 Apple 内置机制(NotificationCenter、Combine)进行比较,并提供适用于 iOS/macOS 的实践示例。
什么是 Event Bus 和观察者模式?
观察者模式定义了对象之间的一对多关系:当一个对象(发布者)改变其状态时,所有依赖对象(订阅者)都会自动收到通知。
Event Bus(事件总线)是一种集中式机制,允许任何组件发送事件(发布)和接收事件(订阅),而无需直接相互了解。这实现了松耦合原则。
在 Apple 生态系统中,已有内置解决方案:
- NotificationCenter — 经典的 Observer 实现,但在类型安全和安全性方面存在限制。
- Combine — 用于响应式编程的现代框架,提供强大的 Publisher/Subscriber。
然而,自建的 Event Bus 提供了完全的控制权,并且可以更轻松地集成到遗留项目中。
在 Swift 中实现简单的 Event Bus
我们将使用泛型和弱引用来创建一个通用的事件总线,以防止内存泄漏。
import Foundation
// 事件协议protocol Event { }
// Event Bus 实现final class EventBus { static let shared = EventBus() private var observers = [ObjectIdentifier: [WeakObserver]]() private init() { } // 订阅事件 func subscribe<T: Event>(observer: AnyObject, handler: @escaping (T) -> Void) { let id = ObjectIdentifier(T.self) let weakRef = WeakObserver(observer: observer, handler: { event in guard let castedEvent = event as? T else { return } handler(castedEvent) }) if observers[id] != nil { observers[id]?.append(weakRef) } else { observers[id] = [weakRef] } // 清理失效引用 cleanDeadObservers(for: id) } // 发布事件 func publish<T: Event>(_ event: T) { let id = ObjectIdentifier(T.self) guard let observerList = observers[id] else { return } for weakObserver in observerList { weakObserver.handler?(event) } // 移除已释放的对象 cleanDeadObservers(for: id) } // 取消订阅 func unsubscribe(observer: AnyObject, eventType: Event.Type) { let id = ObjectIdentifier(eventType) observers[id]?.removeAll { $0.observer === observer } } private func cleanDeadObservers(for id: ObjectIdentifier) { observers[id]?.removeAll { $0.observer == nil } }}
// 用于弱引用的辅助类private class WeakObserver { weak var observer: AnyObject? var handler: ((Event) -> Void)? init(observer: AnyObject, handler: @escaping (Event) -> Void) { self.observer = observer self.handler = handler }}使用示例
定义自定义事件:
struct UserLoggedInEvent: Event { let userId: String let userName: String}
struct DataLoadedEvent: Event { let data: [String]}在 ViewController 中使用:
class ProfileViewController: UIViewController { override func