Как обновить модель данных с помощью DispatchQueue.main.async/Block/Closures в Swift 3
Я учу Свифта. У меня есть одна проблема.
Проблема- у меня есть DataModel с URL-адресом изображения, поэтому первый раз загрузит изображение с URL-адреса и, конечно, второй раз не будет. Поэтому, когда я получаю изображение в своем блоке, я хочу обновить свою модель данных изображением. Но это не работает.
- Я пробовал с функцией inout
- Также завершение перезвонить
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*
}
}
}
}
2 ответа
Из комментариев model
это struct
,
При прохождении struct
(или любой тип значения) для метода или присвоения его переменной, struct
копируется.
Следовательно model.image = image
на самом деле присваивает image
совершенно новый model
а не к оригиналу model
,
Использование ссылочного типа (class
) это исправит.
Ниже приведено потенциальное решение, основанное на вашем коде, однако, как сказал vadain в комментариях, это немного опасно, поскольку загрузка изображения асинхронна и может вернуть изображение в тот момент, когда ячейка больше не существует.
В идеале вы должны настроить свою модель таким образом, чтобы она была постоянной, и она должна отправить асинхронный запрос для загрузки своего изображения. Затем, когда изображение возвращается, оно обновляет модель, и модель передает сообщение о том, что это изображение было обновлено. Ячейки могут прослушивать и реагировать на обновления модели, пока они существуют.
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
}