Swift में Event Bus और Observer पैटर्न (iOS/macOS)
iOS और macOS डेवलपमेंट में अक्सर ऐप के विभिन्न घटकों के बीच कमजोर रूप से जुड़े इंटरैक्शन को व्यवस्थित करने की आवश्यकता होती है। Observer पैटर्न और इसका Event Bus (ईवेंट बस) के रूप में कार्यान्वयन इस समस्या को हल करने का एक शक्तिशाली उपकरण है। इस लेख में, हम Swift में Event Bus को लागू करने का विस्तार से विश्लेषण करेंगे, जिसमें भाषा की आधुनिक क्षमताओं (Generics, closures, weak references) का उपयोग किया जाएगा।
Observer पैटर्न क्या है?
Observer (प्रेक्षक) पैटर्न ऑब्जेक्ट्स के बीच "एक-से-अनेक" संबंध को परिभाषित करता है। जब एक ऑब्जेक्ट (प्रकाशक) अपनी स्थिति बदलता है, तो उस पर निर्भर सभी ऑब्जेक्ट्स (सब्सक्राइबर) स्वचालित रूप से सूचित और अपडेट हो जाते हैं। यह कठोर युग्मन से बचने और कोड रखरखाव को सरल बनाने में मदद करता है।
Swift में Observer के मूल कार्यान्वयन हैं:
NotificationCenter— Foundation में निर्मित एक वैश्विक सूचना बस।- Key-Value Observing (KVO) — ऑब्जेक्ट गुणों की निगरानी के लिए तंत्र।
- Combine framework (iOS 13+) — प्रकाशकों और सब्सक्राइबर्स के समर्थन के साथ एक रिएक्टिव फ्रेमवर्क।
हालांकि, अक्सर एक हल्के और टाइप-सुरक्षित कार्यान्वयन की आवश्यकता होती है, खासकर जब legacy-कोड के साथ काम कर रहे हों या उन प्रोजेक्ट्स में जहां Combine उपलब्ध नहीं है।
Event Bus: सरल और लचीला कार्यान्वयन
Event Bus एक केंद्रीय ईवेंट डिस्पैचर है जो आपको सब्सक्राइबर्स के बारे में सीधे जानकारी के बिना ईवेंट्स को सब्सक्राइब और भेजने की अनुमति देता है। हम इसे मेमोरी लीक से बचने के लिए जेनेरिक और कमजोर संदर्भों का उपयोग करके लागू करेंगे।
Event Bus का मूल कार्यान्वयन
import Foundation
// सभी ईवेंट्स के लिए प्रोटोकॉल
protocol Event { }
// विशिष्ट ईवेंट प्रकार
struct UserLoggedInEvent: Event {
let userId: String
let userName: String
}
struct DataLoadedEvent: Event {
let data: [String]
}
// Event Bus क्लास
final class EventBus {
static let shared = EventBus()
private init() {}
// सब्सक्राइबर्स को स्टोर करने के लिए डिक्शनरी
private var subscribers = [ObjectIdentifier: [Any]]()
// ईवेंट पर सब्सक्राइब करें
func subscribe<T: Event>(observer: AnyObject, handler: @escaping (T) -> Void) {
let key = ObjectIdentifier(T.self)
let wrapped = Subscription(observer: observer, handler: handler as Any)
if subscribers[key] != nil {
subscribers[key]?.append(wrapped)
} else {
subscribers[key] = [wrapped]
}
}
// किसी विशिष्ट प्रेक्षक के लिए सभी ईवेंट्स से अनसब्सक्राइब करें
func unsubscribe(observer: AnyObject) {
for key in subscribers.keys {
subscribers[key]?.removeAll(where: { subscription in
if let sub = subscription as? Subscription {
return sub.observer === observer
}
return false
})
}
}
// ईवेंट प्रकाशित करें
func publish<T: Event>(event: T) {
let key = ObjectIdentifier(T.self)
guard let subs = subscribers[key] else { return }
for subscription in subs {
if let sub = subscription as? Subscription {
if let handler = sub.handler as? (T) -> Void {
handler(event)
}
}
}
}
}
// सब्सक्रिप्शन को स्टोर करने के लिए सहायक संरचना
private struct Subscription {
weak var observer: AnyObject?
let handler: Any
init(observer: AnyObject, handler: Any) {
self.observer = observer
self.handler = handler
}
}
Event Bus का उपयोग
// ViewController जो ईवेंट्स पर सब्सक्राइब करता है
class LoginViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// उपयोगकर्ता लॉगिन ईवेंट पर सब्सक्राइब करें
EventBus.shared.subscribe(observer: self) { [weak self] (event: UserLoggedInEvent) in
guard let self = self else { return }
print("उपयोगकर्ता लॉग इन: \(event.userName)")
// UI अपडेट करें
}
}
deinit {
// मेमोरी लीक से बचने के लिए अनसब्सक्राइब करें
EventBus.shared.unsubscribe(observer: self)
}
}
// कोई अन्य क्लास जो ईवेंट प्रकाशित करती है
class LoginService {
func loginUser(userId: String, userName: String) {
// लॉगिन लॉजिक...
// ईवेंट प्रकाशित करें
EventBus.shared.publish(event: UserLoggedInEvent(userId: userId, userName: userName))
}
}