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
相关产品推荐
相关产品推荐

