Swift HTTP请求在部分网络超时,Kotlin应用正常求排查建议
Swift HTTP请求超时问题排查与修复
核心问题分析
你的代码存在几个关键问题,导致部分网络环境下出现超时:
1. 信号量超时设置冲突
post方法中信号量等待超时设为10秒,但URLRequest和URLSession的超时配置是30秒,会导致请求还在正常处理时,信号量先触发超时,造成误判。
2. 重复创建URLSession实例
两段代码中每次请求都新建URLSession,无法复用系统连接池,增加连接建立开销,弱网环境下更容易超时。
3. JSON请求体冗余格式化
JSONSerialization使用.prettyPrinted生成带缩进的JSON,增大请求体体积,弱网下传输时间更长,提升超时概率。
4. 网络检测逻辑冗余且不完善
HasInternet中用NWPathMonitor检测网络后还发送HEAD请求,不仅冗余,且请求失败时未更新isConnected状态,导致网络状态判断错误;同时每次路径变化都触发请求,易造成频繁网络调用。
5. 异步转同步的不良实践
post方法用信号量把异步请求转为同步,若在主线程调用会阻塞UI,且信号量处理逻辑易出错。
修复后的代码示例
1. 优化后的POST请求方法
// 复用全局URLSession实例,避免重复创建 private let urlSession: URLSession = { let config = URLSessionConfiguration.default config.timeoutIntervalForRequest = 30.0 config.timeoutIntervalForResource = 60.0 return URLSession(configuration: config) }() // 改用闭包处理异步结果,移除信号量逻辑 func post(dModel: DialogModel? = nil, url: String, type: responseTypes, body: [String: Any], headers: [headerType], completion: @escaping (Result<String, Error>) -> Void) { guard let url = URL(string: url) else { let error = NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"]) processError(error: error.localizedDescription) completion(.failure(error)) return } var request = URLRequest(url: url) request.httpMethod = "POST" request.timeoutInterval = 30 for header in headers { request.setValue(header.value, forHTTPHeaderField: header.key) } do { // 移除.prettyPrinted,减小请求体体积 request.httpBody = try JSONSerialization.data(withJSONObject: body, options: []) } catch { processError(dModel: dModel, error: error.localizedDescription, type: .report) completion(.failure(error)) return } urlSession.dataTask(with: request) { [weak self] data, response, error in guard let self = self else { return } if let error = error { self.processError(dModel: dModel, error: error.localizedDescription, type: .report) completion(.failure(error)) return } guard let httpResponse = response as? HTTPURLResponse, let unwrappedData = data, let responseString = String(data: unwrappedData, encoding: .utf8) else { let error = NSError(domain: "", code: -2, userInfo: [NSLocalizedDescriptionKey: "Invalid response"]) self.processError(error: error.localizedDescription) completion(.failure(error)) return } self.parse(dModel: dModel, type: type, response: responseString, statusCode: httpResponse.statusCode) completion(.success(responseString)) }.resume() }
2. 优化后的网络状态监测类
class HasInternet: ObservableObject { let monitor = NWPathMonitor() let queue = DispatchQueue(label: "Monitor") @Published var isConnected = false init() { monitor.pathUpdateHandler = { [weak self] path in DispatchQueue.main.async { // 直接用NWPath原生状态判断,无需额外发送请求 self?.isConnected = path.status == .satisfied } } monitor.start(queue: queue) } // 销毁时停止监测,避免内存泄漏 deinit { monitor.cancel() } }
额外建议
- 永远不要在主线程执行同步网络请求,坚持用闭包/Combine处理异步逻辑。
- 可添加请求重试机制,针对弱网下的偶发超时进行自动重试。
- 开启URLSession日志,通过
OSLog查看请求的详细链路,精准定位超时环节。
内容的提问来源于stack exchange,提问作者Joshua Strutton
相关产品推荐
相关产品推荐

