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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 16:44:57