簡體   English   中英

Swift數組未填寫完成塊

[英]Swift array not filled in completion block

我試圖追加數組(我知道一個簡單的任務),但是由於某種原因我的數組為空。 不管我做什么。 這是我的工作:

我想計算總余額(我應該先做金額*價格,然后將其加總)。

所以我以為我會制作一個余額數組,然后將它們加起來,但數組為空:

func getBalances(completion: @escaping (_ balancesArray: [Double])->()){
        var balancesArray = [Double]()
        for f in portfolioArray{
            getPrice(for: f.name!, in: "EUR", completion: { (price) in
                balancesArray.append(f.amount * price)
                //!!!!!!If I print here the array, it is full!!!!!!
            })
        }
        completion(balancesArray)
    }

這是getPrice函數(它返回了價格,我測試過):

func getPrice(for crypto: String, in fiat: String, completion: @escaping (_ price: Double)->()){
        API.getCryptoRates(cryptoSymbol: crypto, fiatSymbol: fiat) { (error, response: [CurrencyResponse]?) in
            if error == nil{
                if let prices = response{
                    guard let p = Double(prices[0].price) else { return }
                    completion(p)
                }
            }
        }
    }

所以我的問題是,為什么它是空的? 如果我是正確的,那么完成應該具有填充數組。 而且不應該有任何線程問題。

有人可以引導我走上正確的道路嗎? 任何回應表示贊賞!

getPrice是異步的。 for循環早在首次調用getPrice之前getPrice完成。

您需要使用DispatchGroup來確保在對getPrice所有調用都完成之前不對completion(balancesArray)進行調用。 請參閱什么是最好的方法來遍歷APi的結果,並知道何時完成? 舉個例子

您還需要確保從單個線程追加到balancesArray以避免並發寫入。 請參閱快速創建線程安全數組以獲取解決方案。

問題是getPrice是異步的,因此當您調用completion異步函數實際上尚未完成執行。 您可以使用DispatchGroup解決您的問題。

您還應確保僅從單個線程寫入balancesArray ,以避免並發問題。

下面的代碼確保完成處理getBalances一次,所有來電只叫getPrice完成,但它不會使balancesArray線程安全的,你可以照顧,由於在解釋斯威夫特創建線程安全數組

func getBalances(completion: @escaping (_ balancesArray: [Double])->()){
    var balancesArray = [Double]()
    let group = DispatchGroup()
    for f in portfolioArray{
        group.enter()
        getPrice(for: f.name!, in: "EUR", completion: { price in
            if let p = price{
                balancesArray.append(f.amount * p)
            }
            group.leave()
        })
    }
    group.notify(queue: .main, execute: {
        completion(balancesArray)
    })
}

您的getPrice函數有缺陷。 您需要確保在所有情況下都調用完成處理程序,即使結果是錯誤的也是如此。 處理網絡請求時,應始終使完成處理程序返回可選值,並且在出現任何問題的情況下,應使用nil值調用completion 如果您想知道使用nil值的原因,還可以使您的閉包返回一個包含可選值和可選Error的元組,例如URLSession.dataTask(with:, completionHandler:) , URLSession.dataTask(with:, completionHandler:)

func getPrice(for crypto: String, in fiat: String, completion: @escaping (_ price: Double?)->()){
    API.getCryptoRates(cryptoSymbol: crypto, fiatSymbol: fiat) { (error, response: [CurrencyResponse]?) in
        if error == nil{
            if let prices = response{
                guard let p = Double(prices[0].price) else { completion(nil); return }
                completion(p)
            } else {
                completion(nil)
            }
        } else {
            completion(nil)
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM