如何解决Swift并发检查中完成闭包内的@Sendable警告?
Swift严格并发检查警告的解决方案
先看原代码:
class DownloadImageAsyncImageLoader { let url = URL(string: "https://picsum.photos/200")! func handleResponse(data: Data?, response: URLResponse?) -> UIImage? { guard let data = data, let image = UIImage(data: data), let response = response as? HTTPURLResponse, response.statusCode >= 200 && response.statusCode < 300 else { return nil } return image } func downloadWithEscaping(completion: @escaping (UIImage?, Error?) -> Void) { URLSession.shared.dataTask(with: url) { [weak self] data, response, error in guard let image = self?.handleResponse(data: data, response: response) else { completion(nil, error) return } completion(image, nil) } .resume() } }
针对两个警告的解决方法
警告1:@Sendable闭包中捕获非Sendable类型的self
若无法将类设为final,可按以下方式处理:
- 确认类的所有属性都是
Sendable兼容类型(本例中URL本身符合Sendable) - 让类显式遵循
Sendable并添加@unchecked标记,这相当于自行保证类及其子类的线程安全性,不会出现并发数据竞争。修改后的类定义如下:
class DownloadImageAsyncImageLoader: @unchecked Sendable { // 原有代码保持不变 }
注意:后续新增属性时,必须确保属性是Sendable或线程安全的,否则会引入隐藏的并发风险。
警告2:@Sendable闭包中捕获非Sendable类型的completion闭包
URLSession.dataTask的回调闭包是@Sendable的,因此它捕获的闭包也必须符合Sendable要求。只需给completion参数添加@Sendable标注即可:
func downloadWithEscaping(completion: @escaping @Sendable (UIImage?, Error?) -> Void) { // 原有代码保持不变 }
这样编译器就会确认该闭包可安全跨线程调用,符合严格并发检查的规则。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

