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

Swift Combine如何实现上游Publisher完成时发射自定义值

最简实现(无需自定义扩展)

如果你的需求只是原Publisher成功完成时生成指定值、错误透传,完全不需要自定义操作符,直接用系统原生的ignoreOutput+append组合即可:

import Combine

func demo() -> AnyPublisher<Int, Error> {
    // 示例空Publisher
    let firstPublisher = Empty<Never, Error>(completeImmediately: true).eraseToAnyPublisher()
    return firstPublisher
        .ignoreOutput() // 忽略所有上游输出(你的场景本就没有输出)
        // 上游完成后追加生成的指定值
        .append(Just(1).setFailureType(to: Error.self))
        .eraseToAnyPublisher()
}

这个方案完全符合你的要求:上游出错直接透传,上游成功完成后才会生成并发射新值,不需要手动管理Cancellable,没有内存泄漏风险。


自定义completionMap扩展实现

如果你需要更通用的、可以自定义处理所有完成事件(包括成功/失败)的扩展,可以按以下方式实现:

import Combine

extension Publisher where Output == Never {
    func completionMap<P: Publisher>(_ transform: (Subscribers.Completion<Failure>) -> P) -> AnyPublisher<P.Output, P.Failure> where P.Failure == Failure {
        self
            // 上游无输出,此处转换无实际执行逻辑,仅为类型匹配
            .map { _ in Subscribers.Completion<Failure>.finished }
            // 捕获上游错误,转换为正常输出的失败事件
            .catch { error in
                Just(.failure(error))
                    .setFailureType(to: Failure.self)
            }
            // 上游成功完成时输出成功事件
            .replaceEmpty(with: .finished)
            // 将完成事件传入转换闭包,返回对应的Publisher
            .flatMap(transform)
            .eraseToAnyPublisher()
    }
}

你给出的示例demo方法可以直接使用这个扩展,不需要做任何修改即可正常运行。


扩展兼容性说明

如果要支持任意输出类型的上游Publisher(不仅限于Output == Never的场景),可以给扩展加ignoreOutput适配:

extension Publisher {
    func completionMap<P: Publisher>(_ transform: (Subscribers.Completion<Failure>) -> P) -> AnyPublisher<P.Output, P.Failure> where P.Failure == Failure {
        self
            .ignoreOutput()
            .map { _ in Subscribers.Completion<Failure>.finished }
            .catch { error in
                Just(.failure(error))
                    .setFailureType(to: Failure.self)
            }
            .replaceEmpty(with: .finished)
            .flatMap(transform)
            .eraseToAnyPublisher()
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 01:24:03