iOS开发:如何通过URLSession扩展统一实现请求响应日志?
实现URLSession全局自动日志记录
完全可以通过扩展URLSession实现请求与响应的自动日志记录,无需在每个调用data方法的位置手动添加日志代码。以下是具体实现方案:
1. 定义日志函数
先把你已有的日志函数完善(或直接使用),用于格式化输出请求、响应及错误信息:
func logRequest(_ request: URLRequest, response: URLResponse?, data: Data?, error: Error?) { print("===== 请求日志 =====") // 输出请求基本信息 if let method = request.httpMethod, let url = request.url { print("请求方法: \(method) | 请求URL: \(url.absoluteString)") } // 输出请求头 if let headers = request.allHTTPHeaderFields { print("请求头: \(headers)") } // 输出请求体(如果是文本格式) if let body = request.httpBody, let bodyStr = String(data: body, encoding: .utf8) { print("请求体: \(bodyStr)") } print("===== 响应日志 =====") // 输出响应状态码 if let httpResp = response as? HTTPURLResponse { print("响应状态码: \(httpResp.statusCode)") print("响应头: \(httpResp.allHeaderFields)") } // 输出响应数据(如果是文本格式) if let data = data, let respStr = String(data: data, encoding: .utf8) { print("响应内容: \(respStr)") } // 输出错误信息 if let error = error { print("请求错误: \(error.localizedDescription)") } print("====================\n") }
2. 扩展URLSession自动触发日志
通过扩展URLSession,包装原生的data相关方法,在请求完成后自动调用日志函数。需要覆盖两种常用的请求方式:async/await版本(iOS 15+)和CompletionHandler版本(兼容旧系统)。
2.1 适配Async/Await版本
extension URLSession { override func data(from url: URL, delegate: URLSessionTaskDelegate? = nil) async throws -> (Data, URLResponse) { let (data, response) = try await super.data(from: url, delegate: delegate) logRequest(URLRequest(url: url), response: response, data: data, error: nil) return (data, response) } override func data(for request: URLRequest, delegate: URLSessionTaskDelegate? = nil) async throws -> (Data, URLResponse) { let (data, response) = try await super.data(for: request, delegate: delegate) logRequest(request, response: response, data: data, error: nil) return (data, response) } }
2.2 适配CompletionHandler版本
extension URLSession { func dataTask(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask { return super.dataTask(with: request) { data, response, error in logRequest(request, response: response, data: data, error: error) completionHandler(data, response, error) } } func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask { let request = URLRequest(url: url) return self.dataTask(with: request, completionHandler: completionHandler) } }
3. 注意事项
- 上述扩展会对
URLSession.shared及所有自定义URLSession实例生效,无需修改原有请求代码; - 日志函数中可根据实际需求调整输出格式,比如过滤敏感字段(如token、密码)、将日志写入文件而非仅打印控制台;
- 对于
async/await版本的扩展,需确保项目部署目标为iOS 15.0+; - 若使用了自定义
URLSessionTaskDelegate,需注意代理方法与日志逻辑的兼容性。
内容的提问来源于stack exchange,提问作者travis
相关产品推荐
相关产品推荐

