Reputation: 15061
Lets say I have a publisher like this:
NotificationCenter.default.publisher(for: NSNotification.Name.NSManagedObjectContextObjectsDidChange)
.map { notification in /.. do something ../}
how do I make it so that in my block, I stop the publisher from emitting?
I could make it a trymap and then throw an error. But it's so weird to have to throw just to indicate a lack of results (in this case, let's say a non relevant NSManagedObject change)
Upvotes: 1
Views: 2233
Reputation: 535944
Another way is to use flatMap
and emit an Empty as the blocker (and a Just otherwise):
NotificationCenter.default.publisher(for: .NSManagedObjectContextObjectsDidChange)
.flatMap { input -> AnyPublisher<Notification, Never> in
if somethingOrOther {
return Just(input).eraseToAnyPublisher()
} else {
return Empty().eraseToAnyPublisher()
}
}
Upvotes: 1
Reputation: 385998
One way is to use the filter
operator. This passes the original input downstream if the predicate is true:
NotificationCenter.default.publisher(for: .NSManagedObjectContextObjectsDidChange)
.filter { note in note.object === myContext }
.map { note in /.. do something ../}
Another way (mentioned by bscothern in a comment) is to use compactMap
. You can transform the input into a different output, or into nil if want to suppress output:
NotificationCenter.default.publisher(for: .NSManagedObjectContextObjectsDidChange)
.compactMap { note in note.object === myContext ? myContext : nil }
.map { context in /.. do something ../}
Upvotes: 3
Reputation: 258413
Here is possible approach based on connectable publisher (the demo is based on SwiftUI). Tested with Xcode 11.3.1 / iOS 13.3
struct TestConnectableNotification: View {
let publisher = NotificationCenter.default.publisher(for: Notification.Name("test")).makeConnectable()
@State private var text = "<none>"
@State private var subscriber: Cancellable? = nil
var body: some View {
VStack {
Text("Current: \(text)")
.onReceive(publisher) { _ in
let value = Int.random(in: 0..<10)
self.text = "\(value)"
}
Button(self.subscriber == nil ? "Enable" : "Disable") {
if nil == self.subscriber {
self.subscriber = self.publisher.connect()
} else {
self.subscriber?.cancel()
self.subscriber = nil
}
}
Button("Post") {
NotificationCenter.default.post(name: NSNotification.Name("test"), object: nil)
}
}
}
}
Upvotes: 1