为Publisher扩展自定义输出类型,将特定ApiError转为.success
解决Swift Publisher中特殊错误转成功的自定义Output方案
1. 定义自定义Output枚举
需要一个能同时容纳正常输出和2233特殊成功场景的类型,用枚举实现最清晰:
// 枚举可根据需求调整关联值类型,若特殊场景无需额外值可改为无关联case enum CustomOutput<NormalOutput> { // 对应Publisher正常发送的输出 case normal(NormalOutput) // 对应code=2233的特殊成功场景,参考示例用Bool,也可替换为Void case code2233Success(Bool) } // 简化版(特殊场景无额外值): // enum CustomOutput<NormalOutput> { // case normal(NormalOutput) // case code2233Success // }
2. 修改Publisher扩展方法
调整扩展方法的回调签名,让Result使用自定义的CustomOutput,并在捕获到目标错误时返回对应成功枚举:
extension Publisher { func sinkToCustomResult(_ result: @escaping ((Result<CustomOutput<Self.Output>, Self.Failure>) -> Void)) -> AnyCancellable { return sink(receiveCompletion: { completion in switch completion { case .failure(let error): // 匹配目标ApiError及code=2233的情况 if let apiError = error as? ApiError, let globalError = apiError.globalErrors.first, globalError.code == 2233 { // 返回特殊成功场景,根据枚举定义调整参数 result(.success(.code2233Success(true))) // 简化版写法:result(.success(.code2233Success)) return // 必须终止后续代码,避免重复发送失败回调 } // 其他错误正常返回失败 result(.failure(error)) case .finished: break } }, receiveValue: { output in // 正常输出返回normal枚举 result(.success(.normal(output))) }) } }
3. 使用示例
调用扩展方法时,通过枚举区分两种成功场景:
// 假设你有一个返回String类型的Publisher let samplePublisher: AnyPublisher<String, ApiError> = ... samplePublisher.sinkToCustomResult { result in switch result { case .success(let customOutput): switch customOutput { case .normal(let content): print("正常请求成功,内容:\(content)") case .code2233Success(let value): print("捕获到code=2233,按成功处理,值:\(value)") // 简化版处理:print("捕获到code=2233,按成功处理") } case .failure(let error): print("请求失败,错误:\(error)") } }
关键说明
- 枚举的作用:原
Result的Output类型固定为Publisher的输出类型,无法同时兼容正常输出和特殊标记,枚举能明确区分两种成功场景,避免类型混淆。 return的必要性:匹配到2233错误后必须终止后续代码,否则会同时发送成功和失败回调,导致逻辑错误。
内容的提问来源于stack exchange,提问作者Marta Paniti
相关产品推荐
相关产品推荐

