swiftswift3closurescapture-list

How to update data model using DispatchQueue.main.async/Block/Closures in Swift 3


I am learning Swift. I have one Problem.

Problem- I have DataModel with image url, So first time will download image from url and of course second time won't. So when I am getting image in my block I want to update my data model with image. But its not working.

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*
            }
        }
    }
}

Solution

  • From the comments model is a struct.

    When passing a struct (or any value type) to a method or assigning it to a variable, the struct is copied.

    Therefore model.image = image is actually assigning image to a brand new model and not to the original model.

    Using a reference type (a class) will fix it.