如何在 Swift 中使用 DispatchQueue.main.async/Block/Closures 更新数据模型 3
How to update data model using DispatchQueue.main.async/Block/Closures in Swift 3
我正在学习Swift。我有一个问题。
问题- 我有带有图像 url 的数据模型,所以第一次将从 url 下载图像,当然第二次不会。所以当我在我的块中获取图像时,我想用图像更新我的数据模型。但是它不起作用。
- 我试过 inout 函数
- 还有completionHander回调
ViewController.swift
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "OffersTableCell", for: indexPath) as! OffersTableCell
var model = offersArray[indexPath.row] as! OffersModel
cell.updateOfferCellWith(model: model, completionHandler: { image in
model.image = image
})///// I am getting image here, but model is not getting update
return cell
}
Cell.Swift
func updateOfferCellWith(model: OffersModel, completionHandler:@escaping (UIImage) -> Void) {
if (model.image != nil) { //Second time this block should be execute, but model image is always nil
DispatchQueue.main.async { [weak self] in
self?.offerImageView.image = model.image
}
}
else{
//First time- Download image from URL
ImageDownloader.downloadImage(imageUrl: model.offerImageURL) { [weak self] image in
DispatchQueue.main.async {[model] in
var model = model
self?.offerImageView.image = image
//model.image = image*//This is also not working*
completionHandler(image)*//Call back*
}
}
}
}
下面是一个基于您的代码的潜在解决方案,但是,正如 vadain 在评论中所说,这有点危险,因为图像加载是异步的,并且可能 return不复存在。
理想情况下,您要做的是以持久化的方式设置您的模型,并且它应该发送异步请求来下载它的图像。然后,当图像返回时它更新模型并且模型广播一条消息说它的图像已更新。细胞可以在存在时收听和响应模型的更新。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "OffersTableCell", for: indexPath) as! OffersTableCell
var model = offersArray[indexPath.row] as! OffersModel
if image = model.image {
// setting directly here... you could call an image on the cell if you want more data encapuslation
cell.offerImageView.image = model.image
} else {
ImageDownloader.downloadImage(imageUrl: model.offerImageURL) { [weak self] image in
DispatchQueue.main.async {
model.image = image
cell.offerImageView.image = image
}
}
}
return cell
}
来自评论 model
是 struct
。
将 struct
(或任何值类型)传递给方法或将其分配给变量时,将复制 struct
。
因此 model.image = image
实际上是将 image
分配给全新的 model
而不是原来的 model
。
使用引用类型 (a class
) 将修复它。
我正在学习Swift。我有一个问题。
问题- 我有带有图像 url 的数据模型,所以第一次将从 url 下载图像,当然第二次不会。所以当我在我的块中获取图像时,我想用图像更新我的数据模型。但是它不起作用。
- 我试过 inout 函数
- 还有completionHander回调
ViewController.swift
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "OffersTableCell", for: indexPath) as! OffersTableCell
var model = offersArray[indexPath.row] as! OffersModel
cell.updateOfferCellWith(model: model, completionHandler: { image in
model.image = image
})///// I am getting image here, but model is not getting update
return cell
}
Cell.Swift
func updateOfferCellWith(model: OffersModel, completionHandler:@escaping (UIImage) -> Void) {
if (model.image != nil) { //Second time this block should be execute, but model image is always nil
DispatchQueue.main.async { [weak self] in
self?.offerImageView.image = model.image
}
}
else{
//First time- Download image from URL
ImageDownloader.downloadImage(imageUrl: model.offerImageURL) { [weak self] image in
DispatchQueue.main.async {[model] in
var model = model
self?.offerImageView.image = image
//model.image = image*//This is also not working*
completionHandler(image)*//Call back*
}
}
}
}
下面是一个基于您的代码的潜在解决方案,但是,正如 vadain 在评论中所说,这有点危险,因为图像加载是异步的,并且可能 return不复存在。
理想情况下,您要做的是以持久化的方式设置您的模型,并且它应该发送异步请求来下载它的图像。然后,当图像返回时它更新模型并且模型广播一条消息说它的图像已更新。细胞可以在存在时收听和响应模型的更新。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "OffersTableCell", for: indexPath) as! OffersTableCell
var model = offersArray[indexPath.row] as! OffersModel
if image = model.image {
// setting directly here... you could call an image on the cell if you want more data encapuslation
cell.offerImageView.image = model.image
} else {
ImageDownloader.downloadImage(imageUrl: model.offerImageURL) { [weak self] image in
DispatchQueue.main.async {
model.image = image
cell.offerImageView.image = image
}
}
}
return cell
}
来自评论 model
是 struct
。
将 struct
(或任何值类型)传递给方法或将其分配给变量时,将复制 struct
。
因此 model.image = image
实际上是将 image
分配给全新的 model
而不是原来的 model
。
使用引用类型 (a class
) 将修复它。