繁体   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