Combine框架下sink如何忽略receiveValue仅监听completion回调
方案1:使用原生ignoreOutput操作符
你之前认为ignoreOutput不符合预期属于使用误区,ignoreOutput会将上游Publisher的Output类型映射为Never,此时Combine原生提供了仅接收完成事件的sink重载,完全符合你想要的调用形式:
CurrentValueSubject<Void, Error>(()) .eraseToAnyPublisher() .ignoreOutput() .sink { completion in switch completion { case .failure(let error): print(error) print("FAILURE") case .finished: print("SUCCESS") } }
方案2:自定义Publisher扩展
如果你不想额外加ignoreOutput操作符,可以直接扩展Publisher实现仅处理完成事件的sink方法:
extension Publisher { func sink(completion: @escaping (Subscribers.Completion<Failure>) -> Void) -> AnyCancellable { return sink( receiveCompletion: completion, receiveValue: { _ in } ) } }
扩展后即可直接使用你理想中的调用形式,不需要额外中间操作:
CurrentValueSubject<Void, Error>(()) .eraseToAnyPublisher() .sink { completion in switch completion { case .failure(let error): print(error) print("FAILURE") case .finished: print("SUCCESS ") } }
更适配场景的Publisher选型
你的场景是单次异步网络请求,仅存在成功/失败两种结果,不需要存储当前值,用Future比CurrentValueSubject更合适,不需要声明无意义的Void初始值:
// 网络请求封装示例 func requestNetwork() -> Future<Void, Error> { return Future { promise in // 此处替换为实际网络请求逻辑 let isSuccess = Bool.random() if isSuccess { promise(.success(())) } else { promise(.failure(NSError(domain: "Network", code: -1, userInfo: nil))) } } } // 调用示例 requestNetwork() .ignoreOutput() .sink { completion in switch completion { case .failure(let error): print(error) print("FAILURE") case .finished: print("SUCCESS") } }
内容的提问来源于stack exchange,提问作者Richard Topchii
相关产品推荐
相关产品推荐

