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

如何解决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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 02:58:24