
用过 JS 的同学应该对 async await 很熟悉了。但是在 swift 中,直到 2021 年的 WWDC swift 5.5,才被苹果正式推出,今天就花一点时间来讲讲新的 async / await 这两个关键字。
在此之前,异步回调都是通过 OC 时代的 Block(闭包)形式进行的。我们来用一个例子说明,比如我们有个 API 对象,可以用来获取用户信息,和设置用户信息。
struct API {
/// 获取用户信息
/// - Parameter callback: 成功回调,返回 User 对象
static func fetchUserInfo(callback: @escaping (User) -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
callback(User())
}
}
/// 设置用户信息
/// - Parameter callback: 成功回调,返回成功或者失败
static func setUserInfo(callback: @escaping (Bool) -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
callback(true)
}
}
}
如果先获取用户信息,修改完成后再更新用户信息,大概代码如下:
API.fetchUserInfo { user in // 获取用户信息
user.name = "xxx" // 更改用户信息
// 更新用户信息
API.setUserInfo { isSucceed in
print(isSucceed ? "用户信息更新成功" : "用户信息更新失败")
}
}
用闭包的方式有几个明显的问题:
-
如果你不清楚 API 内部实现,你并不知道 Block 会回调几次
-
闭包形式容易造成循环引用,导致内存泄漏
-
嵌套地狱,一层一层的 Block 会让代码难以维护
为了避免以上提到的这些问题,我们用 async / await 来重写 API。
struct API {
/// 获取用户信息
/// - Returns: 返回 User 对象
static func fetchUserInfo() async -> User {
try? await Task.sleep(for: .seconds(3))
return User()
}
/// 设置用户信息
/// - Returns: 返回成功或者失败
static func setUserInfo() async -> Bool {
try? await Task.sleep(for: .seconds(3))
return true
}
}
函数上加上 async 关键字,代表这个函数是异步的,调用异步函数时,使用 await 表示代码在等待 async 的方法返回,会暂停当前的代码执行。
改完之后的调用方式:
// 获取用户信息
let user = await API.fetchUserInfo()
// 更改用户信息
user.name = "xxx"
// 更新用户信息
let isSucceed = await API.setUserInfo()
print(isSucceed ? "用户信息更新成功" : "用户信息更新失败")
这样就完美的解决了上面提到的问题。
async 也可以加在计算属性上:
var myProperty: String {
get async {
...
}
}
print(await myProperty)
async 也可以加在函数的闭包参数上:
func myFunction(worker: (Int) async -> Int) -> Int {
...
}
myFunction {
return await computeNumbers($0)
}
点击下方公众号卡片,关注我,每天分享一个关于 iOS 的新知识
本文同步自微信公众号 “iOS新知”,每天准时分享一个新知识,这里只是同步,想要获得更好的体验就来关注我吧!