【问题标题】:With Combine, how can you flatMap with nil-coalescing使用 Combine,您如何使用 nil-coalescing 进行 flatMap
【发布时间】:2020-12-18 08:23:16
【问题描述】:

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

例如:

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

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

【问题讨论】:

  • eraseToAnyPublisher 添加到您的第一个代码 sn-p 有效。
  • 我已经尝试过了,但它不起作用。您可以发布您的答案,以显示您要使用它的确切含义吗?你的意思有点模棱两可。
  • Charles Maria 的回答实际上要好得多。哦,组合单子的力量:)

标签: ios swift reactive-programming combine


【解决方案1】:

有一个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()
        }
    }
}

【讨论】:

  • 这行得通,但不幸的是.publisher 仅在 iOS 14+ 中。我尝试通过 JustcompactMap 的组合来实现相同的解决方案,但它最终变得更加难以理解。
【解决方案2】:

您的原始方法会起作用,只是看起来您需要指定类型,因为编译器在类型推断方面遇到了问题。

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

注意在 combine 中,每个发布者都有自己的类型,每次使用运算符时,它都会返回不同的(链式)类型,因此请随意使用类型擦除器 .eraseToAnyPublisher()。

【讨论】:

    猜你喜欢
    • 2016-06-20
    • 1970-01-01
    • 1970-01-01
    • 2020-09-25
    • 2018-05-07
    • 1970-01-01
    • 2022-09-26
    • 2015-03-02
    • 2017-09-05
    相关资源
    最近更新 更多