Swift中URLSession.data(from:)端点宕机时无返回无抛异常问题
问题分析与解决方案
当端点宕机时,URLSession.shared.data(from:)未抛出异常且函数直接退出,核心原因是URLSession默认超时时间过长,同时可能存在async调用方式不当、缺少必要网络配置的问题。以下是针对性解决步骤:
1. 配置请求超时时间
URLSession默认请求超时为60秒,当端点完全不可达时,请求会卡在连接阶段,不会立刻触发错误。自定义Session配置,设置合理的超时阈值:
// 全局定义带超时配置的URLSession private let customURLSession: URLSession = { let config = URLSessionConfiguration.default config.timeoutIntervalForRequest = 5 // 5秒无响应则触发超时 config.timeoutIntervalForResource = 5 return URLSession(configuration: config) }() func ping() async throws -> String { let call = "\(baseURL)/Ping" guard let url = URL(string: call) else { throw SmartReaderError.invalidURL } do { let (jsonData, response) = try await customURLSession.data(from: url) // 先验证HTTP响应状态码 guard let httpResponse = response as? HTTPURLResponse, 200...299 ~= httpResponse.statusCode else { return "KO" } // 安全解析响应内容 guard let responseString = String(data: jsonData, encoding: .utf8) else { return "KO" } return responseString == "PONG" ? responseString : "KO" } catch { // 捕获超时、连接失败等所有网络错误 print("Ping请求错误: \(error)") return "KO" } }
2. 确保async函数的正确调用
如果调用ping()的Task被意外取消(比如SwiftUI视图销毁时未处理Task),会导致async函数提前退出,错误无法被捕获。调用时需保证Task生命周期合理:
// SwiftUI视图中调用示例 struct ContentView: View { var body: some View { Button("Ping API") { Task { do { let result = try await ping() print("Ping结果: \(result)") } catch { print("初始化错误: \(error)") } } } } }
3. 检查网络权限与ATS配置
- 若使用HTTP请求,需在
Info.plist中配置ATS允许非HTTPS请求(推荐针对特定域名配置,而非全局放开):
<key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>your-api-domain.com</key> <dict> <key>NSIncludesSubdomains</key> <true/> <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key> <true/> </dict> </dict> </dict>
- 若API在本地局域网,需在
Info.plist中添加NSLocalNetworkUsageDescription,说明网络权限用途。
4. 优化错误处理逻辑
原代码用NSString解析数据存在隐式解包风险,改用String可选绑定更安全;同时增加HTTP状态码检查,避免非成功状态码的响应被误处理。
内容的提问来源于stack exchange,提问作者Marcello Bassiato
相关产品推荐
相关产品推荐

