From f9ca3eab78143d3d40233984ee55d04ff5a57163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Pela=CC=81ez?= Date: Thu, 2 Jan 2025 00:18:41 -0600 Subject: [PATCH] Support Multiple Publishers (again) --- .../Publishing/EventPublisherModifier.swift | 2 +- .../Publishing/EventSubscriberModifier.swift | 28 +--------- .../PublisherRegistrarModifier.swift | 53 +++++++++++++++---- 3 files changed, 47 insertions(+), 36 deletions(-) diff --git a/Sources/HierarchyResponder/Internal/Publishing/EventPublisherModifier.swift b/Sources/HierarchyResponder/Internal/Publishing/EventPublisherModifier.swift index 61dfe4a..be454f4 100644 --- a/Sources/HierarchyResponder/Internal/Publishing/EventPublisherModifier.swift +++ b/Sources/HierarchyResponder/Internal/Publishing/EventPublisherModifier.swift @@ -34,7 +34,7 @@ struct EventPublisherModifier: ViewModifier { func body(content: Content) -> some View { content - .publisherRegistrar(for: E.self, id: id, childContainers: $containers) + .publisherRegistrar(for: E.self, id: id, publisher: nil, containers: $containers) .onAppearAndChange(of: containers) { containers in updatePublisher(containers: containers, destination: destination) } diff --git a/Sources/HierarchyResponder/Internal/Publishing/EventSubscriberModifier.swift b/Sources/HierarchyResponder/Internal/Publishing/EventSubscriberModifier.swift index 801f116..b4cdb5a 100644 --- a/Sources/HierarchyResponder/Internal/Publishing/EventSubscriberModifier.swift +++ b/Sources/HierarchyResponder/Internal/Publishing/EventSubscriberModifier.swift @@ -21,7 +21,6 @@ import SwiftUI */ struct EventSubscriberModifier: ViewModifier { @Environment(\.eventSubscriptionRegistrars) var registrars - @Environment(\.responderSafetyLevel) var safetyLevel let id: String let publisher: EventPublisher @@ -34,30 +33,7 @@ struct EventSubscriberModifier: ViewModifier { func body(content: Content) -> some View { content - .publisherRegistrar(for: E.self, id: id, childContainers: $containers) - .onAppearAndChange(of: registrars) { registrars in - registerPublisher(registrars, containers: containers) - } - .onAppearAndChange(of: containers) { containers in - registerPublisher(registrars, containers: containers) - } - .onDisappear(perform: unregisterPublisher) - } - - func registerPublisher(_ registrars: RegistrarDictionary, containers: Set) { - guard let registrar = registrars[ObjectIdentifier(E.self)] else { - let message = "Subscribed to event with no publisher: \(String(describing: E.self))" - switch safetyLevel { - case .strict: fatalError(message) - case .relaxed: return print(message) - case .disabled: return - } - } - let container = PublishersContainer(id: id, publisher: publisher, containers: containers) - registrar.register(container.id, container) - } - - func unregisterPublisher() { - registrars[ObjectIdentifier(E.self)]?.register(id, nil) + .publisherRegistrar(for: E.self, id: id, publisher: publisher, containers: $containers) + } } diff --git a/Sources/HierarchyResponder/Internal/Publishing/PublisherRegistrarModifier.swift b/Sources/HierarchyResponder/Internal/Publishing/PublisherRegistrarModifier.swift index 034694f..2995c85 100644 --- a/Sources/HierarchyResponder/Internal/Publishing/PublisherRegistrarModifier.swift +++ b/Sources/HierarchyResponder/Internal/Publishing/PublisherRegistrarModifier.swift @@ -8,23 +8,32 @@ import SwiftUI extension View { - func publisherRegistrar(for event: E.Type, id: String, childContainers: Binding>) -> some View { - modifier(PublisherRegistrarModifier(event: event, id: id, childContainers: childContainers)) + func publisherRegistrar(for event: E.Type, + id: String, + publisher: EventPublisher?, + containers: Binding>) -> some View { + modifier(PublisherRegistrarModifier(event: event, + id: id, + publisher: publisher, + containers: containers)) } } struct PublisherRegistrarModifier: ViewModifier { + @Environment(\.responderSafetyLevel) var safetyLevel @Environment(\.eventSubscriptionRegistrars) var registrars let id: String - @Binding var childContainers: Set + let publisher: EventPublisher? + @Binding var containers: Set @State var registrar: EventSubscriptionRegistrar - init(event: E.Type, id: String, childContainers: Binding>) { + init(event: E.Type, id: String, publisher: EventPublisher?, containers: Binding>) { self.id = id - self._childContainers = childContainers - self._registrar = .init(initialValue: .init(id: id) { _, _ in }) + self.publisher = publisher + self._containers = containers + self._registrar = .init(initialValue: .init(id: id + "-empty") { _, _ in }) } var updatedRegistrars: [ObjectIdentifier: EventSubscriptionRegistrar] { @@ -36,16 +45,42 @@ struct PublisherRegistrarModifier: ViewModifier { func body(content: Content) -> some View { content .onAppear(perform: createRegistrar) + .onAppearAndChange(of: registrars) { registrars in + registerPublisher(registrars, containers: containers) + } + .onAppearAndChange(of: containers) { containers in + registerPublisher(registrars, containers: containers) + } .environment(\.eventSubscriptionRegistrars, updatedRegistrars) + .onDisappear(perform: unregisterPublisher) } func createRegistrar() { registrar = .init(id: id) { id, container in if let container { - childContainers.update(with: container) - } else if let container = childContainers.first(where: { $0.id == id }) { - childContainers.remove(container) + containers.update(with: container) + } else if let container = containers.first(where: { $0.id == id }) { + containers.remove(container) + } + } + } + + func registerPublisher(_ registrars: RegistrarDictionary, containers: Set) { + guard let registrar = registrars[ObjectIdentifier(E.self)] else { + if publisher == nil { return } // We're on a publisher modifier + let message = "Subscribed to event with no publisher: \(String(describing: E.self))" + switch safetyLevel { + case .strict: fatalError(message) + case .relaxed: return print(message) + case .disabled: return } } + let publisher = self.publisher ?? EventPublisher(id: id) { _ in } + let container = PublishersContainer(id: id, publisher: publisher, containers: containers) + registrar.register(container.id, container) + } + + func unregisterPublisher() { + registrars[ObjectIdentifier(E.self)]?.register(id, nil) } }