0

I am settiing an image onto a tableViewCell with Alamofire

let messageImage = cell?.viewWithTag(6) as! UIImageView
messageImage.image = nil
messageImage.af_setImage(withURL: photoUrl! as URL)

return cell

I am appending each cell item to an array using Firebase:

ref.child("messages").child(ticker.current).queryOrderedByKey().observe(.childAdded, with: {snapshot in

            let snapDict = snapshot.value as? NSDictionary
            let photoUrl = snapDict?["photo_url"] as? String ?? ""

            messageArray.insert(messageCellStruct(photoUrl: photoUrl), at: 0)
         })

Then I am updating the image on the Same Exact URL with FirebaseStorage

When I re-call the cell ViewController that the TableViewCell is in, the image is not changed on the first couple of cells. But as I scroll to older cells the image is updated:

messageArray.removeAll()
tableView.reload()

If I rebuild the app all cell images are how they are supposed to be.

I am assuming this is because of an Observer error or Im not removing the observer. I really dont know.

1.) The cells share the same exact URL im just changing the data.

2.) It seems to be only working when a cell hasnt loaded yet(or been assigned).

3.) It works perfectly fine after I rebuild and run the app.

enter image description here

Maybe I need to clear the Alamofire cach?

husharoonie
  • 431
  • 1
  • 4
  • 19

2 Answers2

0

It sounds like you need to set the old image to nil before you set the image in messageImage.af_setImage(withURL: photoUrl! as URL).

Cell's are supposed to get cleaned up before they are reused: Apple -PrepareForReuse but Apple also says:

For performance reasons, you should only reset attributes of the cell that are not related to content, for example, alpha, editing, and selection state. The table view's delegate in tableView(_:cellForRowAt:) should always reset all content when reusing a cell.

That basically means you Shouldn't set your imageView's image to nil in prepareForReuse BUT if you sub classed the cell you can create a function inside the subclass and in cellForRowAtIndePath call it before you run messageImage.af_setImage(withURL: photoUrl! as URL). Example Below:

Create subclass for cell and name it MyCustomCell

class MyCustomCell: UITableViewCell {

@IBOutlet weak var messageImage: UIImageView!

    func setImageToNil(){
        messageImage.image = nil
        // I don't use AlamoFire and don't know anything about it but if they have something to set the imageView's image to nil you can also try using that instead
    }
}

Inside your tableView's cellForRowAtIndexPath cast the cell then call setImageToNil() before you run messageImage.af_setImage

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

     // 0. cast the cell as MyCustomCell
     let cell = tableView.dequeueReusableCell(withIdentifier: "MyCustomCell", for: indexPath) as! MyCustomCell

     // 1. call the setImageToNil() method and whatever image is inside messageImage will get set to nil every time the cell is reused
     cell.setImageToNil()

     // 2. the new image should always appear because the old image was set to nil
     cell.messageImage.af_setImage(withURL: photoUrl! as URL)

     return cell
}
Lance Samaria
  • 17,576
  • 18
  • 108
  • 256
0

Alamofire saves image cache locally.

Because I was changing data to the Same Exact URL I had to remove the cache.

 UIImageView.af_sharedImageDownloader.imageCache?.removeAllImages()

 UIImageView.af_sharedImageDownloader.sessionManager.session.configuration.urlCache?.removeAllCachedResponses()
husharoonie
  • 431
  • 1
  • 4
  • 19