nicklockwood / AsyncImageView

[DEPRECATED]
http://charcoaldesign.co.uk/source/cocoa#asyncimageview
Other
906 stars 186 forks source link

Lazy Loading UITableView sometimes shows previously queued image #13

Closed inturbidus closed 12 years ago

inturbidus commented 12 years ago

I have a UITableView that is using your AsyncImageView (great stuff btw). If I scroll up and down, I often get a different image than was requested. It seems like it may be a problem with dequeing the proper cell. I usually have to scroll up and down a couple of times.

It seems like it comes when it should be showing default.

nicklockwood commented 12 years ago

Because table cells are recycled, you need to call [AsyncImageLoader cancelLoadingImagesForTarget:] on the table cell image view before you set the new URL in your cellForRowAtIndexPath method, otherwise it may still be loading the image from a previous row. Could that be the problem?

inturbidus commented 12 years ago

I wonder if I have an old version I don't see that method.

Matt

On Thu, Jun 28, 2012 at 4:28 PM, Nick Lockwood < reply@reply.github.com

wrote:

Because table cells are recycled, you need to call [AsyncImageLoader cancelLoadingImagesForTarget:] on the table cell image view before you set the new URL in your cellForRowAtIndexPath method, otherwise it may still be loading the image from a previous row. Could that be the problem?


Reply to this email directly or view it on GitHub:

https://github.com/nicklockwood/AsyncImageView/issues/13#issuecomment-6640646

––––––––––––––––––––––––––––––––––––– Matt Hudson - Founder/Technology –––––––––––––––––––––––––––––––––––––

* * Moving Ideas and Innovation Forward in the Mobile Space

Office: (479) 856-6177 Cell: (479) 313-6431 Website: www.MobileFWD.com http://www.mobilefwd.com/ Email: matt@mobilefwd.com joey@mobilefwd.com Twitter: @MattFWD

inturbidus commented 12 years ago

Found it. I downloaded the new version as well.

nicklockwood commented 12 years ago

There was a similar approach in the earlier version's example code but it required you to know which URL you were cancelling. I've just updated the examples to demonstrate how to use the new cancel method.

inturbidus commented 12 years ago

It still seems to be loading some other image after I ran this: [[AsyncImageLoader sharedLoader] cancelLoadingImagesForTarget:cell.imgPlayer];

nicklockwood commented 12 years ago

Email your project to support at charcoal design dot co dot uk and I'll take a look.

inturbidus commented 12 years ago

Dang Nick you are awesome.

inturbidus commented 12 years ago

Let me do some more debugging and see if I can find it. My project is pretty big.

nicklockwood commented 12 years ago

If you send me the .m file for your table view controller I'll see if I can spot anything obvious.

inturbidus commented 12 years ago

Sent. I really appreciate you supporting this even though you aren't getting paid.

nicklockwood commented 12 years ago

Wait... I'm not getting paid??!

;-)

inturbidus commented 12 years ago

Haha.. do you have a donate button?

nicklockwood commented 12 years ago

Ah, I have an idea. You need to blank out the previous image in the cell after you recycle it, otherwise it will briefly show whatever image was in there the last time the cell was used before the new image loads to replace it.

In my example I always set the image to a loading placeholder, but you aren't using one, so you probably need to nil out the image immediately after you dequeue the cell, like this:

static NSString *cellIdentifier = @"PlayerListingCell";
PlayerListingCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
    cell = [[[NSBundle mainBundle] loadNibNamed:@"PlayerListingCell" owner:self options:nil] objectAtIndex:0];
} else {
    //we're reusing the cell so there may already be an image in it that we need to clear
    cell.imgPlayer.image = nil;
}
inturbidus commented 12 years ago

That solved it. No where is that donate button? :)

On Thu, Jun 28, 2012 at 5:47 PM, Nick Lockwood < reply@reply.github.com

wrote:

Ah, I have an idea. You need to blank out the previous image in the cell after you recycle it, otherwise it will briefly show whatever image was in there the last time the cell was used before the new image load to replace it.

In my example I always set the image to a loading placeholder, but you aren't using one, so you probably need to nil out the image immediately after you dequeue the cell, like this:

static NSString cellIdentifier = @"PlayerListingCell"; PlayerListingCell cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (cell == nil) { cell = [[[NSBundle mainBundle] loadNibNamed:@"PlayerListingCell" owner:self options:nil] objectAtIndex:0]; } else { //we're reusing the cell so there may already be an image in it that we need to clear cell.imgPlayer.image = nil; }


Reply to this email directly or view it on GitHub:

https://github.com/nicklockwood/AsyncImageView/issues/13#issuecomment-6642712

––––––––––––––––––––––––––––––––––––– Matt Hudson - Founder/Technology –––––––––––––––––––––––––––––––––––––

* * Moving Ideas and Innovation Forward in the Mobile Space

Office: (479) 856-6177 Cell: (479) 313-6431 Website: www.MobileFWD.com http://www.mobilefwd.com/ Email: matt@mobilefwd.com joey@mobilefwd.com Twitter: @MattFWD

nicklockwood commented 12 years ago

There's one here: http://www.charcoaldesign.co.uk/source/cocoa

Glad I could help.

Nick

inturbidus commented 12 years ago

Done. Btw the app this is in is called Trivi.al feel free to check it out http://trivi.al

On Thu, Jun 28, 2012 at 5:54 PM, Nick Lockwood < reply@reply.github.com

wrote:

There's one here: http://www.charcoaldesign.co.uk/source/cocoa

Glad I could help.

Nick


Reply to this email directly or view it on GitHub:

https://github.com/nicklockwood/AsyncImageView/issues/13#issuecomment-6642864

––––––––––––––––––––––––––––––––––––– Matt Hudson - Founder/Technology –––––––––––––––––––––––––––––––––––––

* * Moving Ideas and Innovation Forward in the Mobile Space

Office: (479) 856-6177 Cell: (479) 313-6431 Website: www.MobileFWD.com http://www.mobilefwd.com/ Email: matt@mobilefwd.com joey@mobilefwd.com Twitter: @MattFWD

nicklockwood commented 12 years ago

Thanks, will do.

portwatcher commented 10 years ago

A better way to reset image is to reset it in prepareForReuse in your UITableViewCell subclass

- (void)prepareForReuse {
    self.imageView.image = nil;
}
deckyfx commented 10 years ago

Genius.... Thanks

jabbarfast commented 9 years ago

Hi Guys, I am also facing same issue that for a while cell shows the old image and then updates it. I have used prepareForReuse but no luck with it. So can you guys please help me out.

nicklockwood commented 9 years ago

You need to cancel any loading images on the cell before reusing it. Setting imageURL to nil before setting it to the new URL should suffice.

jabbarfast commented 9 years ago

Hi Nick, Thanks a lot for your quick reply. I have tried setting the URL to nil too but it does not work. PFA my code screen shots.

screen shot 2014-12-23 at 4 56 02 pm screen shot 2014-12-23 at 4 56 31 pm

iHiD commented 9 years ago

@nicklockwood: I'm seeing the same issue as @jabbarfast

I have the following code (which I've checked gets called):

    override func prepareForReuse() {
        super.prepareForReuse()

        AsyncImageLoader.sharedLoader().cancelLoadingImagesForTarget(imageView)
        self.imageView.imageURL = nil
    }

However, I still see previous images before the new ones load. I've tried that code in the cell and in the view. I am using a CollectionView, not a TableView so I wonder if that might be the difference?

Could you provide any more ideas for me to explore please?

Thanks in advance for your help and for creating an awesome library :)

cenck09 commented 9 years ago

@iHiD && @jabbarfast

I can't speak for a collectionView, but for a tableview:

When creating a new cell I also create the imageView with a frame:

        asyncImageView = [[AsyncImageView alloc] initWithFrame:CGRectMake(4, 2, iPhoneCellHeight-4  , iPhoneCellHeight-4)];

Give it a tag: asyncImageView.tag = 10;

Then I pass that to a basic imageView and add as subview to cell:

    UIImageView *imageViewForCell = asyncImageView;
   imageViewForCell.frame = asyncImageView.frame;    
    imageViewForCell.contentMode = UIViewContentModeScaleAspectFit;   
   [cell.contentView addSubview:imageViewForCell];

Then after you're done making the new cell, or if you're reusing a cell, but still in cellForRowAtIndex:

AsyncImageView imageView = (AsyncImageView )[cell viewWithTag:10];

//cancel loading previous image for cell, as to not clog things up when a user scrolls fast
[[AsyncImageLoader sharedLoader] cancelLoadingImagesForTarget:imageView];

// Then I clear out the image by setting it to nil imageView.image = nil;

// Tell the imageView to load the new image
imageView.imageURL = [galleryData getURLforImageFileForArtworkWithID:[artworkObject objectId]];

Hope this helps because I had the same problem you're describing, just with a tableView