如何编写有条件地发布的发布者?

时间:2020-03-16 18:25:51

标签: swift combine

让我们说我有一个这样的发布商:

NotificationCenter.default.publisher(for: NSNotification.Name.NSManagedObjectContextObjectsDidChange)
  .map { notification in /.. do something ../}

我如何做到这一点,以便阻止发布者发布?

我可以将其设为trymap,然后引发错误。但是只能抛出异常以指示结果不足(在这种情况下,可以说是不相关的NSManagedObject更改),真是太奇怪了

3 个答案:

答案 0 :(得分:2)

一种方法是使用filter运算符。如果谓词为true,则会将原始输入传递给下游:

NotificationCenter.default.publisher(for: .NSManagedObjectContextObjectsDidChange)
  .filter { note in note.object === myContext }
  .map { note in /.. do something ../}

另一种方式(由bscothern在评论中提及)是使用compactMap。您可以将输入转换为其他输出,或者如果想要抑制输出,则转换为nil:

NotificationCenter.default.publisher(for: .NSManagedObjectContextObjectsDidChange)
  .compactMap { note in note.object === myContext ? myContext : nil }
  .map { context in /.. do something ../}

答案 1 :(得分:0)

这里是基于可连接发布者的可行方法(该演示基于SwiftUI)。使用Xcode 11.3.1 / iOS 13.3进行了测试

demo

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)
            }
        }
    }
}

答案 2 :(得分:0)

另一种方法是使用flatMap并发出Empty作为阻止程序(否则返回Just):

NotificationCenter.default.publisher(for: .NSManagedObjectContextObjectsDidChange)
    .flatMap { input -> AnyPublisher<Notification, Never> in
        if somethingOrOther {
            return Just(input).eraseToAnyPublisher()
        } else {
            return Empty().eraseToAnyPublisher()
        }
    }