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

iOS中URLSession调用OpenWeatherMap API无响应且无报错问题

问题排查与修复方案

嘿,我来帮你拆解这个头疼的问题!你第一个print能正常输出,但URLSession任务内部的代码完全没走到预期的打印逻辑,甚至没抛出错误,结合你的代码和接口返回的JSON,我找到了几个核心问题:

1. JSON类型解析完全匹配错误

你接口返回的JSON外层是一个对象({}),但代码里强行尝试把它转成[[String: String]](数组类型),这直接导致if let json = try JSONSerialization.jsonObject(with: data!) as? [[String: String]]这一行的转换结果为nil,自然不会进入后续代码块,也就看不到那个打印了。

另外,接口返回的JSON里有大量数字、嵌套对象类型的值,你强行转成[String: String]也会失败,这也是解析卡壳的原因之一。

2. URL格式存在错误

你的URL里用了&,这是HTML中对&的转义字符,但直接写在请求URL里应该用&,否则这个URL是无效的,可能导致请求根本发不出去,或者服务器无法正确解析参数。

3. 强制解包有崩溃隐患

代码里用了data!强制解包,如果请求失败(比如网络问题、服务器报错),data会是nil,这时候直接解包会导致崩溃,而且你没做任何错误兜底处理。

修复后的完整代码示例

// 先修复URL的转义字符,把&替换成&
guard let url = URL(string: "http://api.openweathermap.org/data/2.5/forecast/daily?q=\(cityName),PL&mode=json&units=metric&cnt=5&appid=e9f269***") else {
    print("无效的URL,请检查参数格式")
    return
}

// 简化请求创建逻辑,避免重复初始化
var request = URLRequest(
    url: url,
    cachePolicy: Reachability.isConnectedToNetwork() ? .useProtocolCachePolicy : .returnCacheDataElseLoad,
    timeoutInterval: Double.infinity
)

let session = URLSession.shared
print("This does get returned in the console")

let task = session.dataTask(with: request) { data, response, error in
    // 先处理请求层面的错误
    if let error = error {
        print("请求出错:\(error.localizedDescription)")
        return
    }
    
    // 安全解包返回数据
    guard let data = data else {
        print("未接收到返回数据")
        return
    }
    
    do {
        // 先转成任意类型,再匹配正确的外层对象类型
        guard let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] else {
            print("JSON解析为对象失败")
            return
        }
        
        // 提取真正需要的list数组(每日天气数据)
        guard let weatherList = json["list"] as? [[String: Any]] else {
            print("JSON中未找到list数组")
            return
        }
        
        print("This should now be returned in the console")
        // 遍历数组,注意DailyWeatherItem需要适配非String类型的参数
        for weatherData in weatherList {
            if let item = DailyWeatherItem(dictionary: weatherData as NSDictionary) {
                self.weerItemsDag.append(item)
            }
        }
        
        // 注意:UI操作必须在主线程执行,如果getDailyWeatherItems涉及UI更新
        DispatchQueue.main.async {
            self.getDailyWeatherItems(cityName: cityName)
        }
        
    } catch {
        print("JSON解析错误:\(error)")
    }
}
task.resume()

额外注意事项

  • UI操作必须在主线程:URLSession的completionHandler默认在后台线程执行,如果getDailyWeatherItems里有更新UI的逻辑,一定要放在DispatchQueue.main.async中。
  • Reachability校验可靠性:确保你的Reachability.isConnectedToNetwork()方法逻辑正确,否则可能错误地切换缓存策略。
  • API密钥保密:别把appid直接硬编码在代码里,建议用plist文件或者环境变量管理,避免密钥泄露。

内容的提问来源于stack exchange,提问作者Sinan Samet

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:23:36