从服务器下载图像时出现问题
Issue while downloading images from server
我从服务器收到了一个数组对象,然后我想下载那个对象上有一个 属性 的图像。然后我想用数组对象和图像(视图模型)更新 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)
}
}
}
}
请注意,您将硬币设置为空列表,然后使用该空列表调用 displayCoinstList。该列表是异步添加和更新的。
您应该在准备就绪时触发视图控制器重新加载硬币列表。我会在查看图像之前制作硬币列表,然后在收到图像后 - 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
方法包含异步操作,在这种情况下闭包将在return方法之后调用。
并且,在每个异步 getImage
.
之前调用方法 displayCoinsList(viewModel:)
您可以使用 DispatchGroup 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 将无法收到通知,您将被阻止。
我从服务器收到了一个数组对象,然后我想下载那个对象上有一个 属性 的图像。然后我想用数组对象和图像(视图模型)更新 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)
}
}
}
}
请注意,您将硬币设置为空列表,然后使用该空列表调用 displayCoinstList。该列表是异步添加和更新的。 您应该在准备就绪时触发视图控制器重新加载硬币列表。我会在查看图像之前制作硬币列表,然后在收到图像后 - 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
方法包含异步操作,在这种情况下闭包将在return方法之后调用。
并且,在每个异步 getImage
.
displayCoinsList(viewModel:)
您可以使用 DispatchGroup 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 将无法收到通知,您将被阻止。