AFNetworking setImageWithURLRequest sets image in wrong cell after scrolling (iOS, Swift)
I am using a table with dequeueReusableCellWithIdentifier
and afnetworking+uiimageview
. Some of my cells have images and some don't. If I loop through the table before loading the image, the success block will put the image in a reusable, wrong cell. For example, the image was in cell # 2, but after scrolling, it appeared in cell # 8, because at that moment the figure eight took second place. Can be used setImageWithURLRequest
together with dequeueReusableCellWithIdentifier
?
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 have found many similar questions, but I have not found a solution. I tried to add reload
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
into my block of success, but it doesn't help.
UPDATE: I also noticed that I don't have this problem in cases where all of my cells have images. If I understand correctly, the reason is this: AFNetworking aborts the previous request for the same cell when trying to request a new image. But if I have no image in the cell, it will not be interrupted. How can I do this manually?
source to share
When a cell is reused by a table view, the image loading is still processed in the background. When finished, it cell
points to a reusable cell with different content.
You have two options:
- Calling
cancelImageRequestOperation
in image view aftercell.imageView.image = nil
- In the completion handler, do not reference
cell
; instead use your data model to query for the correct cell from your table view.
source to share
Check if a 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()
}
})
source to share