Swift中如何取消URLSession异步函数对应的URLSessionTask?
取消URLSession异步await任务的两种方法
使用URLSession的异步await API时,确实没有直接暴露底层的URLSessionTask供调用cancel(),但有两种实用方式实现任务完成前的取消:
1. 自定义封装API,直接获取并控制底层Task
如果需要主动拿到URLSessionDataTask实例来随时取消,可以用withCheckedThrowingContinuation封装一个带取消能力的异步方法,把底层Task暴露出来:
extension URLSession { func cancellableDataTask(with request: URLRequest) -> (task: URLSessionDataTask, fetch: () async throws -> (Data, URLResponse)) { var task: URLSessionDataTask! let fetch = { try await withCheckedThrowingContinuation { continuation in task = self.dataTask(with: request) { data, response, error in if let error = error { continuation.resume(throwing: error) return } guard let data = data, let response = response else { continuation.resume(throwing: URLError(.badServerResponse)) return } continuation.resume(returning: (data, response)) } task.resume() // 启动任务 }} return (task, fetch) } }
使用示例:
guard let url = URL(string: "https://example.com") else { return } let request = URLRequest(url: url) let (task, fetchData) = URLSession.shared.cancellableDataTask(with: request) // 随时调用取消 task.cancel() // 等待任务结果 do { let (data, response) = try await fetchData() // 处理响应数据 } catch { if (error as NSError).code == URLError.cancelled.rawValue { print("任务已取消") } else { print("请求错误:\(error)") } }
2. 利用Swift Task的取消机制(系统版本要求iOS 15+/macOS 12+)
在iOS 15及以上、macOS 12及以上的系统中,URLSession的异步API已和Swift的Task取消机制深度集成。取消包裹异步请求的Task,底层的URLSessionTask会自动被终止:
guard let url = URL(string: "https://example.com") else { return } let requestTask = Task { do { let (data, response) = try await URLSession.shared.data(from: url) // 处理数据 } catch is CancellationError { print("Swift Task被取消,底层URLSessionTask也已终止") } catch { print("请求异常:\(error)") } } // 取消外层Task,触发底层请求取消 requestTask.cancel()
这种方式无需额外封装,适合不需要直接操作底层Task的场景,代码更简洁。
内容的提问来源于stack exchange,提问作者bomo
相关产品推荐
相关产品推荐

