swift 如何等待任务完成后再继续主线程?

oewdyzsn  于 2023-02-15  发布在  Swift
关注(0)|答案(1)|浏览(327)

一直在学习Swift中的编码,我正在使用playgrounds尝试不同的挑战-开发环境id Xcode。我目前的挑战是调用一个API来获得货币转换并在终端中显示结果。
我遇到的问题是,如果我在任务中放置一个print(information.result),我可以打印结果,但是最后一行代码print(exchange_value)在终端中打印0.0,我的假设是任务还没有完成,因此任务的赋值还没有完成。
是否有一种简单的方法可以等待任务完成后再继续执行主线程?
我还收到了关于Xcode Immutable value 'error' was never used; consider replacing with '_' or removing it中错误捕获的警告-不确定为什么?
提前感谢您的任何建议或指点。

import Foundation

// MARK: - Information
struct Information: Codable {
    let success: Bool
    let query: Query
    let info: Info
    let date: String
    let result: Double
}

// MARK: - Info
struct Info: Codable {
    let timestamp: Int
    let rate: Double
}

// MARK: - Query
struct Query: Codable {
    let from, to: String
    let amount: Int
}

// MARK: - Code

// Placeholder for the final result returned from the call
let exchange_value: Double = 0.0

// Declare the decoder as a JSON decoder
let decoder = JSONDecoder()

// Set up the URL and the API call
let url = "https://api.apilayer.com/exchangerates_data/convert?to=AED&from=GBP&amount=1"
var request = URLRequest(url: URL(string: url)!,timeoutInterval: Double.infinity)
request.httpMethod = "GET"
request.addValue("REAL KEY REMOVED HERE", forHTTPHeaderField: "apikey")

// Create the task to make the request and get the response
let task = URLSession.shared.dataTask(with: request) { data, response, error in
    guard let data = data
    else
    {
        print(String(describing: error))
        return
    }
    do
    {
        // Decode the data retrived from the request
        let information = try decoder.decode(Information.self, from:data)
        
        // Extract the returned value for the exchange value form the data
        let exchange_value = information.result
    } catch let error {
        print("error")
    }

}

task.resume()

// Print the exchange value that was returned form the request
print(exchange_value)
cuxqih21

cuxqih211#

print(exchange_value)运行时,值还没有到达,所以很可能打印出0.0。
要解决这个问题,您可以使用async-await方法,只需将Code部分更改为

// MARK: - Code

let url = "https://api.apilayer.com/exchangerates_data/convert?to=AED&from=GBP&amount=1"
var request = URLRequest(url: URL(string: url)!,timeoutInterval: Double.infinity)
request.httpMethod = "GET"
request.addValue("REAL KEY REMOVED HERE", forHTTPHeaderField: "apikey")

func getExchangeValue(from request: URLRequest) async -> Double? {
    do {
        let (data, _) = try await URLSession.shared.data(for: request)
        let information = try JSONDecoder().decode(Information.self, from: data)
        return information.result
    } catch let error {
        print(error)
        return nil
    }
}

Task {
    let exchange_value = await getExchangeValue(from: request)
    print(exchange_value ?? "something wrong")
}

也可以让函数抛出并在

func getExchangeValue(from request: URLRequest) async throws -> Double {
    let (data, _) = try await URLSession.shared.data(for: request)
    let information = try JSONDecoder().decode(Information.self, from: data)
    return information.result
}

Task {
    do {
        let exchange_value = try await getExchangeValue(from: request)
        print(exchange_value)
    } catch {
        print(error)
    }
}

相关问题