我從服務器收到了一個陣列物件,然后我想下載該物件上具有一個屬性的影像。然后我想用陣列物件和影像(視圖模型)更新 UI。我正在后臺執行緒上下載影像,但我得到的影像有延遲,并且物件根本沒有填充,我做錯了什么?
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)
}
}
}
}
uj5u.com熱心網友回復:
該getImage方法包含異步操作,在這種情況下,閉包將在方法回傳后被呼叫。而且,該方法displayCoinsList(viewModel:)在每個 async 之前被呼叫getImage。
您可以使用DispatchGroup類。
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都需要呼叫 In Method 。complation如果您忘記呼叫它,DispatchGroup 將無法收到通知,您將被阻止。
uj5u.com熱心網友回復:
請注意,您將硬幣設定為空串列,然后使用該空串列呼叫 displayCoinstList。該串列以異步方式附加和更新。您應該在準備就緒時觸發視圖控制器以重新加載硬幣串列。我會在 fetecg 影像之前制作硬幣串列,然后在收到影像后 - 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)
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/412199.html
標籤:
