使用 Combine,你如何使用 nil-coalescing 进行 flatMap

With Combine, how can you flatMap with nil-coalescing

我有一个发出可选输出类型的发布者。如果输出不是 nil,我需要 flatMap 到一个新的发布者,如果是 nil,我需要回退到一个空的发布者。

例如:

[1, nil, 5].publisher // Generic parameter 'T' could not be inferred
    .flatMap {
        [=10=]?.someNewPublisher ?? Empty(completeImmediately: false)
    }
[1, nil, 5].publisher
    .map {
        [=11=]?.someNewPublisher
    }
    .replaceNil(with: Empty(completeImmediately: false)) // Generic parameter 'Failure' could not be inferred
    .flatMap { [=11=] }

我想知道我是不是试图以错误的方式解决这个问题。明确一点,在映射之前过滤 nil 不会解决我的问题,因为这不会用空发布者替换当前发布者(我会继续接收我不应该再接收的元素)。

有一个 Optional.Publisher 类型。如果您对一个可选值调用 .publisher,您将得到一个发布者,它要么生成包装类型,要么立即完成。

optionalValue.publisher.flatMap(\.someNewPublisher)

编辑:

由于此功能受 iOS14+ 的控制,这里有一个扩展创建了相同的功能,但作为一个函数,因此它不会与 publisher 的命名冲突 var.

请注意,我没有将 completeImmediately 设置为 false,它会自动设置为 true,而将其设置为 false 意味着发布者永远不会完成。

extension Optional {
    func publisher() -> AnyPublisher<Wrapped, Never> {
        switch self {
        case let .some(wrapped):
            return Just(wrapped).eraseToAnyPublisher()
        case .none:
            return Empty().eraseToAnyPublisher()
        }
    }
}

您原来的方法可行,只是看起来您需要指定类型,因为编译器在进行类型推断时遇到问题。

在平面地图中指定 return 类型就可以了

请注意,在 combine 中,每个发布者都有自己的类型,每次您使用运算符时,它 return 都是不同的(链接的)类型,因此请随意使用类型橡皮擦 .eraseToAnyPublisher()。