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
相关产品推荐
相关产品推荐

