I have a class that I want subscribe by multiple subscribers. How can I achieve something like this (consider as pseudo code)? Does it possible to implement such events easily without implementing manually Subscription, Publisher with lots of code?
In short, it should be upgraded Delegate pattern. And it could handle Void events potentially. Just creating a Published property of type ([Item], [Item]) is not the case because event with the same repeated data can be sent one by one.
class SomeObservedClass: ObservableObject {
//???
}
//We will have multiple listeners like this
class SomeListener1 {
@Published var observedClass: SomeObservedClass
init() {
observedClass = .init()
//Maybe something like this
observedClass
.publisher(for: .listChanged)
.sink { (addingItems: [Item], removingItems: [Item]) in
//Processing data
}
.store(in: &cancellable)
//Or something like this maybe
observedClass
.onReceive(.listChanged) { (addingItems: [Item], removingItems: [Item]) in
//Processing data
}
}
}
Here is the solution utilising PassthroughSubject. For now the shortest and cleanest one I could produce. Tested with multiple subscribers, works like expected.
class MainClass {
private let sequenceManager: SequenceManager = .init()
private var bucket: Set<AnyCancellable> = []
func subscribeMe() {
//Here is how we use our publisher
sequenceManager
.publisher(for: .onSequenceUpdate)
.receive(on: DispatchQueue.main) //Optionally
.sink { (addingItems, removingItems) in
//Handle new data here
}
.store(in: &bucket)
}
}
//Object we want to publish its changes
class SequenceManager {
private let sequencePublisher = UpdatedSequencePublisher()
private func didUpdate(addingItems: [String], removingItems: [String]) {
//Here we publish changes
sequencePublisher.publish(adding: addingItems, removing: removingItems)
}
}
//Our publisher stuff
extension SequenceManager {
struct UpdatedSequencePublisher: Publisher {
typealias Output = (adding: [String], removing: [String])
typealias Failure = Never
private let passThroughSubject = PassthroughSubject<Output, Failure>()
func receive<S>(subscriber: S) where S : Subscriber, Failure == S.Failure, Output == S.Input {
passThroughSubject.receive(subscriber: subscriber)
}
func publish(adding: [String], removing: [String]) {
passThroughSubject.send((adding, removing))
}
}
func publisher(for event: Event) -> UpdatedSequencePublisher {
switch event {
case .onSequenceUpdate:
return sequencePublisher
}
}
enum Event {
case onSequenceUpdate
}
}