Swift APICaller请求报invalidResponse错误 Postman测试正常如何修复
问题排查与修复方案
1 排查invalidResponse错误
该错误由你代码中guard let response = response as? HTTPURLResponse, response.statusCode == 200判断触发,对应以下常见原因:
- 首先确认你是否开启了HTTP权限:iOS默认禁止HTTP请求,你使用的是HTTP开头的接口地址,需要在Info.plist中添加ATS配置,要么允许全局HTTP访问,要么将当前服务端IP加入例外列表
- 不要直接判断statusCode等于200,先打印实际返回的状态码,3xx/4xx/5xx都会触发该错误,Postman会自动处理重定向、跨域等场景,原生代码不会
- 核对请求头大小写:服务端如果对Header键大小写敏感,你代码中的
authorizetoken是否和Postman中使用的完全一致,部分服务端要求鉴权Header为Authorization - 打印请求endpoint确认拼接后的URL是否正确,若传入的id包含特殊字符、中文、空格,未转义会导致请求异常
2 排查invalidData错误
该错误由JSON解码失败触发,对应以下常见原因:
- 先打印原始响应数据确认结构:很多接口返回的是外层包裹的结构(如
{"code":200,"data":[车辆数组],"msg":"success"}),你直接解析[Vehicles].self必然失败,需要先定义外层的响应结构再取data字段解析 - 打印解码错误信息:你的代码直接吞了解码错误,无法定位是字段缺失、类型不匹配还是字段名不对应
- 确认
Vehicles模型的所有字段类型、字段名和接口返回完全一致,如有可选字段要定义为Optional类型
3 优化后的调试代码
class APICaller { static let shared = APICaller() // 测试建议先换成https接口,或者配置ATS后再用HTTP private let baseURL = "http://000.000.000.000:3030/api/" private init() {} func getVehicles(for id: String, completed: @escaping (Result<[Vehicles],OnTraErrors>) -> Void ){ // 参数编码,避免特殊字符导致URL无效 guard let encodedId = id.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), let url = URL(string: baseURL + "GetVehicles?UserIdentificationValue=\(encodedId)") else { completed(.failure(.invalidURL)) return } print("请求URL: \(url)") var request = URLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 120) request.httpMethod = "GET" request.allHTTPHeaderFields = [ "content-type": "application/json", "authorizetoken": "Bearer NjQzODM2N0NDNDM4NDhCNDk3RkU0NjA0QUY0NjVFS3GE=", "cache-control": "no-cache", ] let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("请求错误: \(error.localizedDescription)") completed(.failure(.unableToComplete)) return } guard let httpResponse = response as? HTTPURLResponse else { print("非HTTP响应") completed(.failure(.invalidResponse)) return } print("响应状态码: \(httpResponse.statusCode)") // 先放开状态码判断,确认实际返回结果 guard (200...299).contains(httpResponse.statusCode) else { completed(.failure(.invalidResponse)) return } guard let data = data else { print("无响应数据") completed(.failure(.invalidData)) return } // 打印原始响应数据 if let responseString = String(data: data, encoding: .utf8) { print("原始响应内容: \(responseString)") } do { let decoder = JSONDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase let vehicles = try decoder.decode([Vehicles].self, from: data) completed(.success(vehicles)) } catch { // 打印解码错误 print("解码失败错误: \(error)") completed(.failure(.invalidData)) } } task.resume() } }
内容的提问来源于stack exchange,提问作者user17416997
相关产品推荐
相关产品推荐

