Как написать издатель, который условно опубликовал sh? - PullRequest
1 голос
/ 16 марта 2020

Допустим, у меня есть такой издатель:

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

как мне сделать так, чтобы в моем блоке я не давал издателю издавать?

Я мог бы сделать это пробной картой, а затем выдать ошибку. Но это так странно - бросать, чтобы показать отсутствие результатов (в данном случае, скажем, несущественное изменение NSManagedObject)

Ответы [ 3 ]

1 голос
/ 16 марта 2020

Одним из способов является использование оператора filter. Это пропускает исходный входной поток, если предикат истинен:

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

Другой способ (упомянутый bscothern в комментарии) - использовать compactMap. Вы можете преобразовать вход в другой выход или в ноль, если хотите подавить вывод:

NotificationCenter.default.publisher(for: .NSManagedObjectContextObjectsDidChange)
  .compactMap { note in note.object === myContext ? myContext : nil }
  .map { context in /.. do something ../}
0 голосов
/ 16 марта 2020

Другим способом является использование flatMap и создание пустого пространства в качестве блокирующего (и просто иначе):

NotificationCenter.default.publisher(for: .NSManagedObjectContextObjectsDidChange)
    .flatMap { input -> AnyPublisher<Notification, Never> in
        if somethingOrOther {
            return Just(input).eraseToAnyPublisher()
        } else {
            return Empty().eraseToAnyPublisher()
        }
    }
0 голосов
/ 16 марта 2020

Здесь возможен подход, основанный на подключаемом издателе (демонстрация основана на 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)
            }
        }
    }
}
...