75142913在线留言
【SwiftUI实用代码】使用URLSession和async/await发送和接收可编程数据_IOS开发_网络人

【SwiftUI实用代码】使用URLSession和async/await发送和接收可编程数据

Kwok 发表于:2021-11-18 10:18:36 点击:74 评论: 0

在今年WWDC21推出的swift5.5里增加了async/await,很方便的让我们可以定义异步操作。

iOS为我们提供了从互联网发送和接收数据的内置工具,如果我们将其与Codable支持相结合,那么可以将Swift对象转换为JSON进行发送,然后接收回JSON以转换为Swift对象。更好的是,当请求完成后,我们可以立即将其数据分配给SwiftUI视图中的属性,从而导致我们的用户界面更新。

为了演示这一点,我们可以从苹果的iTunes API加载一些示例音乐JSON数据,并将其显示在SwiftUI的List视图上。苹果的数据包含大量信息,但我们将将其缩减为两种类型:Result将存储轨道ID、名称和它所属的专辑,Response将存储一系列结果。

一、定义Model数据结构

因此,我们先建立一个解码使用的结构体,从以下代码开始:

struct Response: Codable {
    var results: [Result]//将返回的结果解码
}
    //返回结果的结构组成
struct Result: Codable {
    var trackId: Int
    var trackName: String
    var collectionName: String
}

二、定义View视图

本演示中为了让代码简单明了,所以我将不会使用ViewModel,我们现在可以编写一个简单的ContentView,显示一系列结果: 

struct ContentView: View {
    @State private var results = [Result]()
    
    var body: some View {
        List(results, id: \.trackId) { item in
            VStack(alignment: .leading) {
                Text(item.trackName)
                    .font(.headline)
                Text(item.collectionName)
            }
        }.task {//在此视图出现时执行的异步任务。.onAppear则是同步任务
            await loadData()
        }        
    }
        //使用async定义一个异步执行的函数
    func loadData() async {
        guard let url = URL(string: "https://itunes.apple.com/search?term=%E5%91%8A%E7%99%BD%E6%B0%A3%E7%90%83/&entity=song") else {
            print("URL无效,请检查输入~")
            return
        }
        do {
            let (data, _) = try await URLSession.shared.data(from: url)//执行异步等待
            if let decodedResponse = try? JSONDecoder().decode(Response.self, from: data) {
                results = decodedResponse.results
                print("任务执行成功",results)
            }
        } catch {
            print("数据解码失败,请检查~")
        }
    }
}

程序在启动会不会显示任何东西,因为results数组是空的。当视频展示时,我们激活了.task修饰器,通过await让其等待loadData()函数异步执行完成,然后将返回后的数据解码并传递给results,try await 我们的URLSession:将要求iTunes API向我们发送周杰伦歌曲的列表,然后使用JSONDecoder将这些结果转换为Result实例数组。

任何能够运行SwiftUI的iPhone每秒钟都可以执行数十亿次操作,速度如此之快,以至于在我们意识到它启动它之前就完成了大多数工作。另一方面,网络从互联网下载数据可能需要数秒或更长时间,对于一台当时习惯于做十亿件其他事情的计算机来说,这非常慢。

Swift没有强迫我们在网络发生时停止整个进度,而是让我们能够说“这项工作需要一些时间,所以请等待它完成,而应用程序的其余部分继续照常运行。”

这种功能在我们的主要应用程序代码继续工作时让一些代码运行的能力被称为异步函数async。同步函数是在根据需要返回值之前完全运行的函数,但异步函数是能够进入睡眠状态一段时间的函数,以便它可以等待其他一些工作完成后才能继续。在我们的情况下,这意味着在我们的网络代码发生时入睡,这样我们应用程序的其余部分就不会冻结几秒钟。

注意里面的新async关键字让我们告诉Swift,为了完成工作,这个功能可能想进入后台运行,不要影响前面的任何工作。

我们希望在List显示后立即运行它,但我们不能在这里使用onAppear(),因为它不知道如何处理睡眠功能,onAppear是一个同步执行的功能。

SwiftUI为此类任务提供了不同的修饰符,仅调用task()很有帮助。这可以调用可能进入睡眠一段时间的函数;Swift要求我们做的只是用第二个关键字标记这些函数,await,所以我们明确承认可能会发生睡眠。

提示:将await视为try——我们说我们理解可能会发生睡眠,就像try说我们承认可能会抛出错误一样。

在loadData(),我们需要完成三个步骤:

  1. 创建我们要抓取的URL。
  2. 获取该URL的数据。
  3. 将这些数据的结果解码为Response结构。

这带来了三件重要的事情,所以让我们分解一下:

  1. 我们的工作正在通过data(from:)方法完成,该方法获取URL并在该URL返回Data对象。此方法属于URLSession类,如果您愿意,您可以手动创建和配置该类,但您也可以使用带有合理默认值的共享实例。
  2. 来自data(from:)的返回值是一个元组,包含URL上的数据和一些描述请求进展的元数据。我们不使用元数据,但我们确实想要URL的数据,因此下划线——我们为数据创建一个新的本地常量,并将元数据扔掉。
  3. 当同时使用try和await时,我们必须编写try await——不允许使用await try。这没有特殊的原因,但他们必须选择一个,所以他们选择了读起来更自然的。
除非注明,网络人的文章均为原创,转载请以链接形式标明本文地址:https://www.55mx.com/post/177
标签:asyncawaitKwok最后编辑于:2021-11-18 10:18:29
0
感谢打赏!

《【SwiftUI实用代码】使用URLSession和async/await发送和接收可编程数据》的网友评论(0)

本站推荐阅读

热门点击文章