You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:08:06