iOS Swift4开发:URLSession请求成功但返回空JSON数据问题
嘿,我来帮你排查这个问题!既然Postman能正常拿到接口数据,说明后端服务本身没问题,问题大概率出在你的Swift代码实现上。先看看你贴的代码片段里的几个明显语法错误,再一步步排查潜在问题:
先修正代码里的语法错误
你给出的代码片段里有两个基础语法问题,这会直接导致代码无法编译执行:
- 类型别名里的
void应该是大写的Void:Swift中空返回类型的正确写法是Void(或者直接用()),小写的void是C语言的关键字,这里会报错。修正后:typealias JSONCompletionHandler = (Data?, Int?, Error?) -> Void - 定义静态函数的关键字是
func不是function:Swift里函数定义的正确写法是static func,不是static function。修正后:static func getData(completionHandler: @escaping JSONCompletionHandler) { // 你的请求代码 }
接下来的排查步骤(修正语法后仍无数据的情况)
1. 检查URL是否有效
确保你创建的URL对象不是nil,如果URL格式有问题(比如包含特殊字符、拼写错误),URL(string:)会返回nil。可以在代码里加个判断:
guard let url = URL(string: "http://apiurl.com") else { completionHandler(nil, nil, NSError(domain: "InvalidURL", code: -1, userInfo: ["message": "URL格式错误"])) return }
如果确实是URL格式问题,建议用URLComponents来构建URL,能自动处理特殊字符转义。
2. 确保网络请求被正确发起
如果你的代码里用了URLSession的dataTask,一定要记得调用task.resume(),不然请求根本不会发送出去。完整的请求示例:
static func getData(completionHandler: @escaping JSONCompletionHandler) { guard let url = URL(string: "http://apiurl.com") else { completionHandler(nil, nil, NSError(domain: "InvalidURL", code: -1, userInfo: ["message": "URL格式错误"])) return } let task = URLSession.shared.dataTask(with: url) { data, response, error in // 解析响应 guard let httpResponse = response as? HTTPURLResponse else { completionHandler(nil, nil, error ?? NSError(domain: "NoResponse", code: -2, userInfo: ["message": "未收到响应"])) return } completionHandler(data, httpResponse.statusCode, error) } // 必须调用resume()启动请求 task.resume() }
3. 检查ATS设置
iOS 9及以后默认开启了ATS(App Transport Security),会拦截非HTTPS的网络请求。如果你的接口是HTTP协议,需要在Info.plist里添加ATS例外配置:
- 右键点击
Info.plist选择"Open As" -> "Source Code" - 添加以下代码:
<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>
Postman不受ATS限制,所以能正常请求,但App里会被拦截,这是很常见的坑。
4. 检查请求头和参数是否匹配Postman
Postman里可能设置了特定的请求头(比如Authorization、Content-Type)或者请求参数,但你的Swift代码里没添加。比如如果接口需要认证令牌,要给请求添加头:
var request = URLRequest(url: url) request.addValue("Bearer your_auth_token", forHTTPHeaderField: "Authorization") request.addValue("application/json", forHTTPHeaderField: "Content-Type") let task = URLSession.shared.dataTask(with: request) { data, response, error in // 处理响应 } task.resume()
5. 确保在主线程更新UI
当你拿到数据后,更新Picker或TableView的操作必须在主线程执行,不然UI不会刷新。调用completionHandler的时候记得切换到主线程:
getData { data, statusCode, error in DispatchQueue.main.async { if let data = data { // 解析JSON数据 do { let json = try JSONSerialization.jsonObject(with: data, options: []) // 更新Picker/TableView的数据源 // 比如:yourPicker.dataSource = ... // yourTableView.reloadData() } catch { print("JSON解析失败:\(error)") } } else { print("请求错误:\(error?.localizedDescription ?? "未知错误")") } } }
按照这个步骤一步步排查,应该能找到问题所在!
内容的提问来源于stack exchange,提问作者E.Mattu
相关产品推荐
相关产品推荐

