0

If we fetch a small image (say, 60 x 60) from the Internet, inside of the method:

-(UITableViewCell *) tableView:(UITableView *) tableView 
                       cellForRowAtIndexPath:(NSIndexPath *)indexPath {  ...  }

What if there are a fixed 25 number of rows vs if the length can be variable (say, 100, or can be 1000)? If we use dequeueReusableCellWithIdentifier to "reuse" a cell, and we probably will need to remove the subviews in this cell (one of which is the 60 x 60 image), and so when the user scroll up and down the list, the cells are reused, and images are re-fetched from the net, and it can be pausing here and there while scrolling.

But if I remove the dequeueReusableCellWithIdentifier and always allocate a new cell:

    cell = [[UITableViewCell alloc] 
               initWithStyle:UITableViewCellStyleDefault
               reuseIdentifier:TableViewCellIdentifier];

then when I scroll down and up again, the NSLog shows that the images are still being fetched. Is there a way to prevent that, if we don't want to use an array separately to store the fetched images?

(right now, the behavior is, initially, about 7 images are fetched, and if the table is scrolled down 3 rows, then 3 images are fetched, and if the table is scrolled back up 3 rows, then 3 images are fetched again)

nonopolarity
  • 146,324
  • 131
  • 460
  • 740

5 Answers5

2

you should have an image caching mechanism. download the image if it does not exist. Set an expiration where you will need to refetch it. Then display it.

Next time you load it. you display the already downloaded image and check the expiration. If its expired you download it again, and update the display.

pretty simple.

Only complication is, after the download should the image be over written. I test this with a GUID. When the image download is requested I put a UUID in the tableview or image object itself. I also send that UUID along with the download task. when the download returns you test the download's UUID against the display item's UUID. if they are Equal. then you update the display. if they have changed, then another download was requested and overrode yours. Therefore the images was changed by that process and a download will be finishing soon that does have that UUID and will change the image with its downloaded contents.

Hope that helps :)

The Lazy Coder
  • 11,560
  • 4
  • 51
  • 69
  • what if the page is guaranteed to be only 25 images only... can all 25 cells (UITableViewCell objects) be drawn so that no re-drawing is needed when the user scroll up and down? If the first 7 images are loaded when the cells are requested, looks like it will delay the display of cells... and if we use a placeholder and use a separate thread to put the image in when each is loaded, then it feels like we are implementing a small part of a web browser – nonopolarity Aug 23 '12 at 02:35
  • the UITableView will only keep the UITableViewCell's that are visible on the screen. Alive in memory. You will use dequeueReusableCellWithIdentifier to get cells that you previously created. This will reduce the overhead. And if you really want to keep the UIImages in memory you can do that as well. but its not that costly to open them multiple times. Unless they are extremely large images. – The Lazy Coder Aug 23 '12 at 02:44
1

You could use image caching as Volure mentioned. I also suggest you implement some form of lazy loading for those images. There are many different implementations for this. This project is a subclass of UIImageView that supports asynchronous loading.

Also, take a look at this question, the answers could be helpful.

hope this helps.

Community
  • 1
  • 1
KDaker
  • 5,899
  • 5
  • 31
  • 44
1

As far as the scroll view pausing your should load your images (if they are not cached or need updating as per DarkAngel's answer) on another thread. I'd use NSOperationQueue. Here's a good tutorial on setting up NSOperationQueue. A good idea is to use a shared queue in your app delegate that you can just add tasks to when you need it.

1

Just use SDWebImage or AFNetworking. They both offer a category of UIImageView giving you the caching mechanism.

What that means is if the image downloader library (SDWebImage or AFNetworking) has found an image in its cache, then it will just get that one from disk rather than redownload the image from the web.

You're seeing that lag is most likely because in your cellForRowAtIndexPath: table view delegate method, you're probably downloading the thumbnail image using NSURLConnection on the main thread.

SDWebImage or AFNetworking will essentially do all the hard work for you and make your table responsive. All that you have to do is really:

[myThumbnailImageView imageWithURL:imageURL placeholder:[UIImage imageNamed:@"myPlaceholderImage.png"]];

Once you got that line in there, that's it. Your real image will appear once its downloaded, until then you can continue to smoothly scroll the table view. Each cell will display a placeholder image that you specified (see above line of code) when the image has not been downloaded.

Zhang
  • 11,549
  • 7
  • 57
  • 87
0

For More convenience to download image use EGOImageLoader/EGOImageView Download this class by this link https://github.com/enormego/EGOImageLoading.

From this EGOCache is used to store your image. First time you download, while scrolling the UITableview get the image from EGOCache store. In that class it store the Downloaded image with key. The key is hashed value of your imageUrl. Use same key to retrieve your image from cache. Tamilarasan

TamilKing
  • 1,643
  • 1
  • 12
  • 23