Swift 5.5 新特性

2022-08-16 15:21:28 浏览数 (1)

WWDC21上发布了Swift 5.5,虽然是小版本,但是特性不少……

Async/await

SE-0296提案终于为开发者带来了期待已久的 async/await,语法基本上和javascript中的很像。

老的方式

以前写异步函数像这样

代码语言:javascript复制
func fetchWeatherHistory(completion: @escaping ([Double]) -> Void) {
    // Complex networking code here; we'll just send back 100,000 random temperatures
    DispatchQueue.global().async {
        let results = (1...100_000).map { _ in Double.random(in: -10...30) }
        completion(results)
    }
}

func calculateAverageTemperature(for records: [Double], completion: @escaping (Double) -> Void) {
    // Sum our array then divide by the array size
    DispatchQueue.global().async {
        let total = records.reduce(0,  )
        let average = total / Double(records.count)
        completion(average)
    }
}

func upload(result: Double, completion: @escaping (String) -> Void) {
    // More complex networking code; we'll just send back "OK"
    DispatchQueue.global().async {
        completion("OK")
    }
}

这样调用

代码语言:javascript复制
fetchWeatherHistory { records in
    calculateAverageTemperature(for: records) { average in
        upload(result: average) { response in
            print("Server response: (response)")
        }
    }
}

存在的问题是

  • 回调函数很容易调用多次,或者忘记调用。
  • 函数参数 @escaping (String) -> Void 看着也不直观
  • “回调地狱”看起来也不美观
  • 在Swift 5.0 增加了Result 类型之前,返回错误也困难。

Swift 5.5 Async/await方式

代码语言:javascript复制
func fetchWeatherHistory() async -> [Double] {
    (1...100_000).map { _ in Double.random(in: -10...30) }
}

func calculateAverageTemperature(for records: [Double]) async -> Double {
    let total = records.reduce(0,  )
    let average = total / Double(records.count)
    return average
}

func upload(result: Double) async -> String {
    "OK"
}

使用也更简单

代码语言:javascript复制
func processWeather() async {
    let records = await fetchWeatherHistory()
    let average = await calculateAverageTemperature(for: records)
    let response = await upload(result: average)
    print("Server response: (response)")
}

Async / await 错误处理

swift 5.5 async 函数也可以像普通函数一样抛出错误 async throws

代码语言:javascript复制
enum UserError: Error {
    case invalidCount, dataTooLong
}

func fetchUsers(count: Int) async throws -> [String] {
    if count > 3 {
        // Don't attempt to fetch too many users
        throw UserError.invalidCount
    }

    // Complex networking code here; we'll just send back up to `count` users
    return Array(["Antoni", "Karamo", "Tan"].prefix(count))
}

func save(users: [String]) async throws -> String {
    let savedUsers = users.joined(separator: ",")

    if savedUsers.count > 32 {
        throw UserError.dataTooLong
    } else {
        // Actual saving code would go here
        return "Saved (savedUsers)!"
    }
}

使用也是类似

代码语言:javascript复制
func updateUsers() async {
    do {
        let users = try await fetchUsers(count: 3)
        let result = try await save(users: users)
        print(result)
    } catch {
        print("Oops!")
    }
}

0 人点赞