为什么即使现代并发向后兼容,我仍会看到有关“数据(for:delegate:) 仅在 iOS 15.0+ 上可用”的错误

Swift 5.5 为 iOS 15 及更高版本引入了具有新 Async / Await 的现代并发,但很快,随着 Xcode 13.2(以及随后的 13.2.1)的发布,它使我们能够使用 AsyncAwait 为 iOS 13+、macOS 10.15+ 等进行开发。但是,当我尝试发出这样的异步请求时:

let (data, response) = try await URLSession.shared.data(for: request)

它不能在 iOS 13+ 上运行。相反,我收到一条错误消息:

data(for:delegate:) 仅适用于 iOS 15.0 或更高版本

当我将最小部署目标设置为 iOS 15.0 时,该错误消失了,但我希望该软件支持 iOS 13.0+。我知道 data(for:delegate:) 仅在 iOS 15.0+ 上受支持,但如果我无法发出异步网络获取请求,那么向后兼容 13.0+ 又有什么意义?

stack overflow Why do I see an error about 'data(for:delegate:) is only available on iOS 15.0+' even though modern concurrency is backward compatible
原文答案
author avatar

接受的答案

this Swift by Sundell article 中所述:

尽管 Swift 5.5 的新并发系统在 Xcode 13.2 中变得向后兼容,但一些利用这些新并发功能的内置系统 API 仍然仅在 iOS 15、macOS Monterey 和 Apple 2021 的其余版本中可用操作系统。

这就是 John 为一种方法复制 async/await 驱动的 URLSession API 的方式:

@available(iOS, deprecated: 15.0, message: "Use the built-in API instead")
extension URLSession {
    func data(from url: URL) async throws -> (Data, URLResponse) {
         try await withCheckedThrowingContinuation { continuation in
            let task = self.dataTask(with: url) { data, response, error in
                 guard let data = data, let response = response else {
                     let error = error ?? URLError(.badServerResponse)
                     return continuation.resume(throwing: error)
                 }

                 continuation.resume(returning: (data, response))
             }

             task.resume()
        }
    }
}

答案:

作者头像

这是另一个可以处理 URL 请求而不仅仅是 URL 的变体:

@available(iOS, deprecated: 15.0, message: "Use the built-in API instead")
extension URLSession {
    func data(from request: URLRequest) async throws -> (Data, URLResponse) {
         try await withCheckedThrowingContinuation { continuation in
             let task = self.dataTask(with: request, completionHandler: { data, response, error in
                 guard let data = data, let response = response else {
                     let error = error ?? URLError(.badServerResponse)
                     return continuation.resume(throwing: error)
                 }

                 continuation.resume(returning: (data, response))
             })

             task.resume()
        }
    }
}