Using AlamofireImage Inside UITableViewCell
Asked Answered
C

1

9

I've been reading a lot of answers here saying that by using AlamofireImage helper methods (e.g. af_setImageWithURL()) or any equivalent library, you don't need to worry about cell reusing stuff (Plus, many published tutorials actually just do that). That is to say, I don't have to keep a weak reference to the cell or getting it by using tableView's cellForRowAtIndexPath() method to update its imageView after the background downloading finishes, like what we usually do if request made manually.

First of all, is that true? And if so, how it was done inside the library, cause I tried to trace AlamofireImage's af_setImageWithURL() code, and I cannot find any effort made to make sure we're still working on the same cell we made the request from. Am I missing something?

I am sorry if it sounds stupid, but I am really confused.

Clump answered 21/12, 2015 at 20:16 Comment(3)
AlamofireImage doesn't do anything to automatically avoid cell reuse issues.Amine
So you are telling me that all those tutorials just do it wrong, that is really interesting! But yeah, it makes a lot more sense now...Clump
Well I'm not sure what tutorials you're talking about but I wouldn't be surprised if some of them did things wrong.Amine
P
14

Assuming you're talking about the UIImageView category, yes, it does solve a number of problems that plague naïve asynchronous image retrieval issues, namely:

  • If a cell is inserted above or below the cell in question, the fact that the NSIndexPath has changed will not affect the asynchronous updating of the image for the cell in question.

  • If you scroll quickly to row 100, as you call af_setImageWithURL on reused cells, the requests for prior rows that were previously associated with this reused cell will be canceled.

    • One implication of this is that it avoids the image view for a visible row getting updated with the image request for the image for the row previously associated with this reused cell. (This avoids the "flickering" of images on slow connections that simplistic implementations can experience.)

    • Another implication of this is that it avoids the performance problem where the image associated for cell 100 could get backlogged behind the image request for rows 1-99.

  • AlamofireImage also provides image resizing routine, which is important when showing thumbnail images for cells. If you don't resize images, you can have extravagant memory usage if using large assets (especially in collection views in which many thumbnail images may be visible).

In terms of UITableViewCell issues that AlamofireImage might not handle as gracefully as we'd like, it includes:

  • Regarding caching, AlamofireImage relies upon the underlying NSURLCache rather than doing its own caching via NSCache or to local persistent storage. While I understand why the author did that (there's a certain intuitive appeal, insofar as NSURLCache should be able to do this elegantly), you should be aware that NSURLCache can be problematic, only cacheing in accordance with poorly documented rules (if resource exceeds 5% of total cache size, it doesn't get cached; it won't cache if the HTTP headers aren't quite right, etc.). So one has to be careful on the caching issue.

  • Regarding preheating (the prefetching of images for cells that are adjacent to the visible rows), AlamofireImage doesn't do much here. You might want to see some low priority request management for cells that are adjacent to the visible rows, so that visible cell performance isn't adversely affected, but also so that the images associated with those rows are already when the user scrolls.

Bottom line, it is an overstatement to say "you don't need to worry about cell reusing stuff" when using a UIImageView category. You still need to carefully design your cell reuse logic, e.g.:

  • Make sure you don't have any paths that bypass the updating of the image view, even if the row in question might not have an image to show;
  • Identify whether image resizing is necessary;
  • Confirm that NSURLCache is caching correctly in your situation;
  • Decide whether you want to create and cache thumbnails;
  • Etc.

But it is true that a well-executed UIImageView category can forestall many pitfalls of overly-simplistic asynchronous image retrieval routines. But it's no silver bullet.

Pliocene answered 14/2, 2016 at 18:31 Comment(3)
All are clear now. Thank you for your perfect answer.Clump
I've found that AlamofireImage's UIImageView category doesn't work so well with UITableViewCells (at least, not out of the box). After the async request completes, the cell needs to be refreshed, and this doesn't happen automatically. We can do it in the completion block for setImageWithURL, but we can then get into an infinite loop, re-fetching the image (even from the cache) and repeating the process indefinitely. If anyone has found a good solution to this, I'd love to hear it.Simmer
All asynchronous UIImageView extensions are going to suffer from this. The simplest approach is to use a fixed cell layout. If you need dynamic layout, then yes, you need to refresh/reload the cell, but check to see if you've already retrieved the cell before initiating another request (e.g. some state variable that indicates whether the image has already been retrieved).Pliocene

© 2022 - 2024 — McMap. All rights reserved.