📜  swift await async - Swift (1)

📅  最后修改于: 2023-12-03 15:20:24.741000             🧑  作者: Mango

Swift中的 await 和 async

在 Swift 5.5 中,引入了异步操作的新特性——asyncawait。这两个关键字使得异步编程变得更加优雅和高效。

异步编程

在传统的编程中,我们常常使用阻塞式的方法来等待一个操作的完成。比如在加载网络资源时,我们会使用 URLSessiondataTask 方法,然后等待回调函数来获取数据。

let url = URL(string: "https://example.com")
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
    if let error = error {
        // 处理错误
        return
    }
    guard let data = data else {
        // 处理错误
        return
    }
    // 处理数据
}
task.resume()

这样的代码存在一个问题,就是它会阻塞当前线程,因为我们需要等待 dataTask 的回调才能继续执行下面的代码。在某些情况下,这可能会导致 UI 的卡顿,甚至程序的崩溃。

另一种解决这个问题的方法是使用 GCD(Grand Central Dispatch)。我们可以通过 GCD 来切换线程,使得当前线程不会被阻塞。但是 GCD 代码常常难以理解和维护。

let url = URL(string: "https://example.com")
let queue = DispatchQueue.global(qos: .userInitiated)
queue.async {
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        if let error = error {
            // 处理错误
            return
        }
        guard let data = data else {
            // 处理错误
            return
        }
        // 处理数据
    }.resume()
}
asyncawait

在 Swift 5.5 中,可以使用 asyncawait 来简化异步编程的操作。asyncawait 是成对出现的,async 用于标记异步函数,await 用于等待异步函数完成。

下面是一个例子,使用 asyncawait 来加载一个网络资源:

enum NetworkError: Error {
    case requestFailed
    case unknown
}

func loadData(from url: URL) async throws -> Data {
    let (data, response) = try await URLSession.shared.data(from: url)
    guard let httpURLResponse = response as? HTTPURLResponse,
        (200...299).contains(httpURLResponse.statusCode) else {
        throw NetworkError.requestFailed
    }
    return data
}

do {
    let url = URL(string: "https://example.com")!
    let data = try await loadData(from: url)
    // 处理数据
} catch {
    // 处理错误
}

在这个例子中,我们使用 async 来标记 loadData 函数为异步函数。在函数内部,我们使用 await 等待 URLSession.shared.data 函数完成。

需要注意的是,异步函数返回的是一个 Task 对象,而不是最终的返回值。在使用 await 等待完成时,返回值将被提取并返回,而 Task 对象也可能包含一些有用的附加信息。

异步块

除了异步函数,还可以使用异步块来进行异步操作,例如:

async {
    // 异步操作
}

异步块内部的代码会立即将控制权返回给上层调用者,然后在后台异步执行,与 GCD 中的 DispatchQueue.global().async { } 类似。

结论

在 Swift 5.5 中,asyncawait 提供了一种更加优雅和高效的方法来处理异步操作。它们简化了异步编程的代码,并提高了性能和可维护性。我们应该尽可能地使用 asyncawait 来代替传统的阻塞式和 GCD 异步编程。