You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Combine中`compactMap { $0 }`的简写:能否通过扩展实现`compactMap()`?

实现无闭包的compactMap()语法糖移除Publisher中的nil值

当然可以实现这种语法糖,直接给Combine的Publisher扩展一个无参的compactMap()方法,专门处理输出为可选类型的流,自动过滤nil并解包非可选值。

实现代码

import Combine

// 定义协议统一处理可选类型
protocol OptionalType {
    associatedtype Wrapped
    var wrappedValue: Wrapped? { get }
}

// 让所有Optional类型遵循该协议
extension Optional: OptionalType {
    var wrappedValue: Wrapped? { self }
}

// 给Publisher扩展无参compactMap
extension Publisher where Output: OptionalType {
    func compactMap() -> Publishers.CompactMap<Self, Output.Wrapped> {
        compactMap { $0.wrappedValue }
    }
}

使用示例

假设你有一个输出可选类型的Publisher:

var cancellables = Set<AnyCancellable>()
let optionalNumberPublisher = PassthroughSubject<Int?, Never>()

// 原来的写法
optionalNumberPublisher
    .compactMap { $0 }
    .sink(receiveValue: { print("原写法输出:\($0)") })
    .store(in: &cancellables)

// 现在的语法糖写法
optionalNumberPublisher
    .compactMap()
    .sink(receiveValue: { print("语法糖写法输出:\($0)") })
    .store(in: &cancellables)

// 发送测试值
optionalNumberPublisher.send(1)
optionalNumberPublisher.send(nil)
optionalNumberPublisher.send(2)

说明

  • 这个扩展仅对输出为可选类型的Publisher生效,如果你的Publisher输出不是可选值,调用compactMap()会直接编译报错,避免误用。
  • 内部其实还是调用了系统的compactMap方法,只是帮你省略了重复写{ $0 }的步骤,完全符合你想要的简化效果。

内容的提问来源于stack exchange,提问作者Trev14

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 22:49:58