通过 Swift 的 async await 语法糖进行 URLSession
WWDC 21 过后,Swift 也推出了 async await 语法糖,并且麻烦的 URLSession.shared.dataTask 闭包 也拥有了新的语法糖版本
采用 async await 的 URLSession 能够有效的帮助我们避免在使用闭包时可能出现的线程问题
如果想了解完整的详情内容,可以查看 Apple Developer 的视频
这就是今天本文要提到的 URLSession.shared.data
URLSession.shared.data
支持两种参数,一种是 from
接受普通的 URL
类型并且快速进行 HTTP GET 请求
一种是 for
接受 URLRequest
类型请求,可以创建 URLRequest 类型的变量来对请求定义 HTTP 方法,Headers,Body 等等属性
如果你还没有了解 URLRequest,可以试试看上次的文章 在 Swift 5 和 SwiftUI 中通过 URLRequest 与 URLSession 请求 JSON 并反序列化 或者访问 Apple Developer Documentation
因为 URLSession.shared.data 的使用方式都一样,为了简单演示,在这里将会使用 URL 直接发送 GET 请求
我们可以在 Xcode 中建立一个 Swift Playground
一个美丽的空项目就这么被构建出来了
这篇文章采用一个 Mock API 作为演示,我们管它叫做 Movie Ticket,API 可以返回一些当日的电影票数据
它包括了
- 电影名字
- 电影类型
- 电影票的价格
- 电影时长 (分钟)
Swift 作为静态类型语言,我们需要先建立这个数据的结构体或者类
1 | struct MovieTicket: Codable { |
这将会是接下来进行 Decode 时候要用到的结构体,请注意,这个结构体必须要遵循 Decodable
协议,当然你也可以遵守 Codable
协议
接着,我们会建立一个 async function
1 | func getTodaysMovie() async throws -> [MovieTicket] { |
在使用全新的 URLSession.shared.data
的时候,错误将不会再放入以前的闭包中,而是使用 try 来获取错误,因此请在方法指纹中加入 throws
为了接下来可以抛出一些自定义的错误,我将创建一些我自己希望抛出的错误
1 | enum MyError: Error { |
当意外发生时,我可以 throw
出这些错误
就像这样,使用 throw
来代替 fatalError()
URLSession.shared.data(from: URL)
方法将会回传一个带有 data
和 response
的元组
因此通过如此描写来取回数据
1 | let (data, response) = try await URLSession.shared.data(from: url) |
如果不需要检查 response,可以使用 _
来代替 response
在此,我们还是执行最佳做法,检查 response 中的 HTTP Status Code 来查看是否是正常的返回
1 | guard |
我们需要先将 URLResponse
类型的 response
转换为 HTTPURLResponse
的 response
并且检查 response
的 statusCode
是否等于 200,不等于将会抛出自定的 MyError.invlidServerResponse
错误
检查完毕后,就可以将 data
通过 Swift 自带的 JSONDecoder 转换为可供我们访问的 MovieTicket
类型数据
1 | let decoded = try JSONDecoder().decode([MovieTicket].self, from: data) |
因为服务器返回给我们的数据类型是多个 MovieTicket
的列表,所以使用中括号把 MovieTicket
包裹住,最后一步 return
好了,想看看服务器会返回什么数据吗
在这个方法外面的下面写点东西
1 | Task { |
1 | import Cocoa |