簡體   English   中英

從服務器下載圖像時出現問題

[英]Issue while downloading images from server

我從服務器收到了一個數組 object,然后我想下載該 object 上具有一個屬性的圖像。 然后我想用數組對象和圖像(視圖模型)更新 UI。 我正在后台線程上下載圖像,但我得到的圖像有延遲,並且 object 根本沒有填充,我做錯了什么?

func presentCoinse(_ list: Home.Models.CoinseListResponse) {
        var coins = [Home.Models.coinsViewModel]()
        for item in list {
            getImage(symbol: item.symbol) { image in
                let i = Home.Models.coinsViewModel(image: image,
                                                   symbol: item.symbol,
                                                   name: item.name,
                                                   buyPrice: item.buyPrice,
                                                   sellPrice: item.sellPrice,
                                                   change24Hource: item.symbol)
                coins.append(i)
            }
        }
        viewController?.displayCoinsList(viewModel: coins)
    }

    private func getImage(symbol: String, complation: @escaping(_ image: Data?) -> Void) {
        
        queue.async {
            if let url = URL(string: "\(CDN_URL)\(symbol).png") {
              
                let data = try? Data(contentsOf: url)
                
                DispatchQueue.main.async {
                    complation(data)
                }
            }
        }
    }

請注意,您將硬幣設置為空列表,然后使用該空列表調用 displayCoinstList。 該列表以異步方式附加和更新。 您應該觸發視圖 controller 以在准備好后重新加載硬幣列表。 我會在拍攝圖像之前制作硬幣清單,然后在收到圖像后 - UIImageView 將自行渲染。

    func presentCoinse(_ list: Home.Models.CoinseListResponse) {

            // async part srarts here

            var coins = [Home.Models.coinsViewModel]()
            for item in list {
                getImage(symbol: item.symbol) { image in
                    let i = Home.Models.coinsViewModel(image: image,
                                                       symbol: item.symbol,
                                                       name: item.name,
                                                       buyPrice: item.buyPrice,
                                                       sellPrice: item.sellPrice,
                                                       change24Hource: item.symbol)
                    coins.append(i)
                }
            }

            // async part ends here

            viewController?.displayCoinsList(viewModel: coins)
        }

你所做的相當於:

func presentCoinse(_ list: Home.Models.CoinseListResponse) {
        var coins = [Home.Models.coinsViewModel]()
        viewController?.displayCoinsList(viewModel: coins) // coins in empty at this point)

        for item in list {
            getImage(symbol: item.symbol) { image in
                let i = Home.Models.coinsViewModel(image: image,
                                                   symbol: item.symbol,
                                                   name: item.name,
                                                   buyPrice: item.buyPrice,
                                                   sellPrice: item.sellPrice,
                                                   change24Hource: item.symbol)
                coins.append(i)
            }
        }
    }

getImage方法包含異步操作,在這種情況下,閉包將在方法返回后被調用。 而且,方法displayCoinsList(viewModel:)在每個異步getImage之前被調用。

您可以使用調度組 class。

func presentCoinse(_ list: Home.Models.CoinseListResponse) {
    var coins = [Home.Models.coinsViewModel]()
    let dispatchGroup = DispatchGroup() // add a dispatch group 
    
    for item in list {
        dispatchGroup.enter() // increment group counter before async call
        getImage(symbol: item.symbol) { image in
            defer {
                dispatchGroup.leave() // decrease group counter in every condition with 'defer'
            }
            let i = Home.Models.coinsViewModel(image: image,
                                               symbol: item.symbol,
                                               name: item.name,
                                               buyPrice: item.buyPrice,
                                               sellPrice: item.sellPrice,
                                               change24Hource: item.symbol)
            coins.append(i)
        }
    }
    dispatchGroup.notify(queue: .main) {
        // wait all async calls are completed
        viewController?.displayCoinsList(viewModel: coins)
    }
}

private func getImage(symbol: String, complation: @escaping(_ image: Data?) -> Void) {
    
    queue.async {
        if let url = URL(string: "\(CDN_URL)\(symbol).png") {
            let data = try? Data(contentsOf: url)
            complation(data)
        } else {
            complation(nil)
        }
    }
}

注意:在getImage方法中需要在每種情況下調用complation 如果您忘記調用它,DispatchGroup 將無法收到通知,您將被阻止。

暫無
暫無

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

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