Swift 5+Alamofire+Combine+MVVM fetchData返回unknown错误如何解决
解决步骤
- 第一步:先还原真实错误类型,不要吞掉原始错误
你当前代码里的.mapError{_ in APIError.unknown}把所有Alamofire抛出的错误都统一转成了unknown,无法定位具体问题,先修改这部分逻辑,把错误类型对应上:
func fetchData(from endpoint:ScrapeAPI )->AnyPublisher<T, APIError>{ return AF.request(endpoint.mockurl, method: .post, parameters: endpoint.parameters, encoder: JSONParameterEncoder.prettyPrinted, headers: endpoint.headers) .validate() .publishDecodable(type:T.self) .value() .mapError { afError -> APIError in // 匹配解码错误 if let decodingError = afError.underlyingError as? DecodingError { return .decodingError } // 匹配状态码错误 else if let statusCode = afError.responseCode { return .errorCOde(statusCode) } // 其他未知错误 else { return .unknown } } .receive(on: DispatchQueue.main) .eraseToAnyPublisher() }
改完后重新运行,就能确认是不是解码环节抛出的问题。
- 第二步:打印原始响应数据,确认返回结构符合预期
在解码逻辑前插入原始数据打印逻辑,确认返回的JSON和你预期的结构一致:
return AF.request(endpoint.mockurl, method: .post, parameters: endpoint.parameters, encoder: JSONParameterEncoder.prettyPrinted, headers: endpoint.headers) .validate() .publishData() // 先获取原始响应数据 .handleEvents(receiveOutput: { response in // 将Data转成字符串打印 if let data = response.data, let jsonStr = String(data: data, encoding: .utf8) { print("返回的原始JSON内容:\n\(jsonStr)") } }) .publishDecodable(type: T.self) // 后续逻辑保持不变
拿到原始JSON后,和你定义的泛型T的属性逐一比对,检查字段名、字段类型是否匹配,比如JSON里的字段是蛇形命名(如user_id),而你T里的属性是驼峰(如userId),默认解码规则下就会失败。
- 第三步:手动解码验证泛型T的匹配性
如果确认返回JSON结构没问题,可以单独做解码验证,捕捉详细的解码错误信息,能直接定位到不匹配的字段:
// 可以用上面步骤打印拿到的原始Data,或者把.responseJSON获取到的字典转成Data let rawJsonData = /* 从响应中获取的原始Data */ let decoder = JSONDecoder() // 如果JSON是蛇形命名,需要添加这个配置 // decoder.keyDecodingStrategy = .convertFromSnakeCase // 如果有自定义日期格式,也要补充对应配置 // decoder.dateDecodingStrategy = .formatted(自定义日期格式器) do { let result = try decoder.decode(T.self, from: rawJsonData) print("解码成功: \(result)") } catch let decodingError as DecodingError { print("解码失败详细信息: \(decodingError)") // 这里会明确输出是哪个字段缺失、类型不匹配还是键名不对应 } catch { print("其他错误: \(error)") }
- 第四步:检查Alamofire解码的Decoder配置
Alamofire的publishDecodable方法默认使用无配置的JSONDecoder(),如果你有自定义解码规则,需要主动传入配置好的Decoder:
let customDecoder = JSONDecoder() customDecoder.keyDecodingStrategy = .convertFromSnakeCase // 其他自定义配置 .publishDecodable(type: T.self, decoder: customDecoder)
内容的提问来源于stack exchange,提问作者tumen khureltulga
相关产品推荐
相关产品推荐

