John Kakon
John Kakon

Reputation: 2541

AFNetworking's setImageWithURLRequest sets image in wrong cell after scroll (iOS, Swift)

I use table with dequeueReusableCellWithIdentifier and afnetworking+uiimageview. Some of my cells have images, some haven't. If I scroll my table before an image has loaded, success block will put image in reused wrong cell. For example image was in cell #2, but after scroll it appears in cell number #8 because #8 was on second position in that moment. Is it possible to use setImageWithURLRequest with dequeueReusableCellWithIdentifier together?

My code:

    let cell = tableView.dequeueReusableCellWithIdentifier("simpleCell", forIndexPath: indexPath) as UITableViewCell!
    cell.textLabel.text = fields[indexPath.row]["name"] as String
    cell.imageView.image = nil
    if let image = fields[indexPath.row]["image"] as? String {
        if (image != "") {
            let image_url = NSURL(string: image)
            let url_request = NSURLRequest(URL: image_url)
            let placeholder = UIImage(named: "no_photo")
            cell.imageView.setImageWithURLRequest(url_request, placeholderImage: placeholder, success: { [weak cell] (request:NSURLRequest!,response:NSHTTPURLResponse!, image:UIImage!) -> Void in
                if let cell_for_image = cell {
                    cell_for_image.imageView.image = image
                    cell_for_image.setNeedsLayout()
                }
            }, failure: { [weak cell]
               (request:NSURLRequest!,response:NSHTTPURLResponse!, error:NSError!) -> Void in
                if let cell_for_image = cell {
                    cell_for_image.imageView.image = nil
                    cell_for_image.setNeedsLayout()
                }
            })
        }
    }
    return cell

sorry if my question duplicates another. I found a lot of similar questions, but I haven't found solution. I tried to add reload

tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)

into my success block, but it doesn't help.

UPDATE: I also noticed, that I have not this problem in cases when all my cells has an images. If I understood correctly the reason is: AFNetworking is aborting previous request for the same cell, when try to request new image. But If I haven't image in cell it will not abort. How can I do it manually?

Upvotes: 3

Views: 5133

Answers (2)

Aaron Brager
Aaron Brager

Reputation: 66244

When the cell is reused by the table view, the image download is still processing in the background. When it completes, cell points to a reused cell with different content.

You have two options:

  1. Call cancelImageRequestOperation on the image view after cell.imageView.image = nil
  2. In the completion handler, don't refer to cell; instead use your data model to request the correct cell from the table view.

Upvotes: 4

tmagalhaes
tmagalhaes

Reputation: 984

Check if the cell is visible

let visibleCells = tableView.visibleCells as NSArray
cell.imageView.setImageWithURLRequest(url_request, placeholderImage: placeholder, success: { [weak cell] (request:NSURLRequest!,response:NSHTTPURLResponse!, image:UIImage!) -> Void in
                if let cell_for_image = cell {
                    if(visibleCells.containsObject(cell)) {
                      cell_for_image.imageView.image = image
                      cell_for_image.setNeedsLayout()
                    }

                }
            }, failure: { [weak cell]
               (request:NSURLRequest!,response:NSHTTPURLResponse!, error:NSError!) -> Void in
                if let cell_for_image = cell {
                    cell_for_image.imageView.image = nil
                    cell_for_image.setNeedsLayout()
                }
            })

Upvotes: 0

Related Questions