0

I have added a table view, and I am display image in the cells. I have also added this code:

So that the cells resize depending on the image.

When I launch my app though, I get this : [![enter image description here][1]][1]

And the images do not load untill I start scrolling...If I scroll down half the page then go back to the top, I get this: Which is correct

[![enter image description here][2]][2]

Any ideas? I have researched on google and tried the odd solution for the older versions of Xcode, But nothing seems to work!

Here is the rest of my code from the TableViewController:

  • Images are redundant, they make your question hard to read. Please remove the images and put your implementation, specifically `cellForRowAtIndexPath`. – Kof Dec 23 '15 at 16:05
  • if your images height are fixed to a constant value, and your constraints are properly placed the height of the cell should be properly calculated. maybe what is happening is that your images are overlapping to the next cell because they don't have the property `clipToBounds = true` – Lucho Dec 23 '15 at 16:43
  • @Lucho how would I set that property? –  Dec 23 '15 at 16:51
  • `yourImageView.clipsToBounds = true` you could do that on your PostTableViewCell.swift file if you have one – Lucho Dec 23 '15 at 16:52
  • Please don't deface your questions. If the question is a mistake, delete it - if not, let it be. Thanks! :) – Eric Aya Jan 12 '16 at 10:27

1 Answers1

1

Image isn't loaded correctly in cellForRowAtIndexPath delegate method, you're (probably) downloading the image in the background, so cellForRowAtIndexPath is returned before image is ready.

Downloaded image is probably cached somewhere so next time it's loaded properly.

post.downloadImage() better have a callback closure to be called when image was downloaded, to assign the downloaded image into the proper cell.

Keep in mind that user may scroll this cell out of the screen before image is loaded, so you better use a unique id to abort downloaded image assignment if cell has already changed.

Here's an example for a method that downloads an image in the background, then assigns it to the cell -

+ (void)loadImage:(NSString *)imageUrl onComplete:(void(^)(UIImage *image, BOOL loaded, NSString *callIdentifier))callback callIdentifier:(NSString *)callIdentifier {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul), ^{
        [self downloadPicture:url onComplete:^(UIImage *image, BOOL loaded) {
            dispatch_sync(dispatch_get_main_queue(), ^{
                callback(image, loaded, callIdentifier);
            });
        }];
    });

    callback([UIImage imageNamed:@"placeholder"], NO, callIdentifier);
}

+ (void)downloadPicture:(NSString *)url saveTo:(NSString *)filePath onComplete:(void (^)(UIImage *image, BOOL loaded))onComplete {
    NSError *error = nil;
    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url] options:NSDataReadingMappedAlways error:&error];
    if (!error) {
        UIImage *image = [UIImage imageWithData:data scale:GTUserPictureScale];
        if (onComplete)
            onComplete(image, YES);
    } else {
        NSLog(@"Error loading user picture: %@", [error description]);
        if (onComplete)
            onComplete([UIImage imageNamed:@"missing"], NO);
    }
}

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

    // ...

    __weak MyClass *wself = self;

    self.imageUrl = @"http://...";
    [self loadImage:self.imageUrl onComplete:^(UIImage *image, BOOL loaded, NSString *callIdentifier) {

        @synchronized(wself) {
            if ([callIdentifier isEqualToString:wself.imageUrl]) {
                if (loaded) {
                    wself.image = image;
                }
            } else
                NSLog(@"Expired load image request for id %@", callIdentifier);
        }

    } callIdentifier:self.imageUrl];

    // ...
}
Kof
  • 23,893
  • 9
  • 56
  • 81
  • 1
    Thank you, my theory was correct - you download the image within `cellForRowAtIndexPath` method, it's probably running in the background and saved into a cache (maybe UIImage's cache?) so next time it's loaded instantly, as it was already downloaded. – Kof Dec 23 '15 at 16:50
  • 1
    It is saved to a UIImage Cache, so what would you say I need to do to fix this issue? –  Dec 23 '15 at 16:53
  • 1
    Just update the original cell after download is finished. Make sure this cell still **wants** this image, it's possible that user the cell has been reused since. – Kof Dec 23 '15 at 17:09
  • 1
    Thanks for this, I have tried several different things but cant seem to fix it! I have added the code of when I download the image above, maybe you might know what the problem is! –  Dec 23 '15 at 18:22