Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazy Loading UITableView sometimes shows previously queued image #13

Closed
inturbidus opened this issue Jun 28, 2012 · 24 comments
Closed

Lazy Loading UITableView sometimes shows previously queued image #13

inturbidus opened this issue Jun 28, 2012 · 24 comments

Comments

@inturbidus
Copy link

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
Copy link
Owner

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
Copy link
Author

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 <
[email protected]

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:

#13 (comment)

–––––––––––––––––––––––––––––––––––––
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: [email protected] [email protected]
Twitter: @MattFWD

@inturbidus
Copy link
Author

Found it. I downloaded the new version as well.

@nicklockwood
Copy link
Owner

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
Copy link
Author

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

@nicklockwood
Copy link
Owner

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

@inturbidus
Copy link
Author

Dang Nick you are awesome.

@inturbidus
Copy link
Author

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

@nicklockwood
Copy link
Owner

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

@inturbidus
Copy link
Author

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

@nicklockwood
Copy link
Owner

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

;-)

@inturbidus
Copy link
Author

Haha.. do you have a donate button?

@nicklockwood
Copy link
Owner

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
Copy link
Author

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

On Thu, Jun 28, 2012 at 5:47 PM, Nick Lockwood <
[email protected]

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:

#13 (comment)

–––––––––––––––––––––––––––––––––––––
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: [email protected] [email protected]
Twitter: @MattFWD

@nicklockwood
Copy link
Owner

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

Glad I could help.

Nick

@inturbidus
Copy link
Author

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 <
[email protected]

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:

#13 (comment)

–––––––––––––––––––––––––––––––––––––
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: [email protected] [email protected]
Twitter: @MattFWD

@nicklockwood
Copy link
Owner

Thanks, will do.

@portwatcher
Copy link

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

- (void)prepareForReuse {
    self.imageView.image = nil;
}

@deckyfx
Copy link

deckyfx commented Aug 25, 2014

Genius....
Thanks

@profmuhammadjabbar
Copy link

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
Copy link
Owner

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.

@profmuhammadjabbar
Copy link

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
Copy link

iHiD commented Aug 21, 2015

@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
Copy link

cenck09 commented Aug 21, 2015

@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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants