Loading images asynchronously in a UITableView with auto-detection

I have a UITableView that loads images asynchronously in a UITableView. Since all images have different heights, I set the height limit according to the height of the image.

This works fine when I use DataWithContentsOfUrl, but freezes the user interface. When I load asynchronously, images accumulate one above the other like this:

http://i.stack.imgur.com/TEUwK.png

The code I use is as follows:

NSURL * imageURL = [NSURL URLWithString:img];
NSURLRequest* request = [NSURLRequest requestWithURL:imageURL];
cell.imageViewHeightConstraint.constant=0;
[NSURLConnection sendAsynchronousRequest:request    queue:[NSOperationQueue mainQueue]  completionHandler:^(NSURLResponse * response,   NSData * data,  NSError * error) {
    if (!error){
        UIImage *imgz = [UIImage imageWithData:data];
        [cell.CellImg setBackgroundImage:imgz forState:UIControlStateNormal];
        [cell.CellImg sizeToFit];
        cell.imageViewHeightConstraint.constant=result.width*(imgz.size.height/imgz.size.width);
        [cell setNeedsUpdateConstraints];
    }
}];
[cell updateConstraints];

When I scroll up and down several times, the images correctly position themselves.

+4
source share
3

, reloadRowsAtIndexPaths , , , . , https://graph.facebook.com/v2.1/%@/?access_token=%@&fields=attachments , . cellForRowAtIndexPath cell.imageViewHeightConstraint.constant . , , , , .

0

. , (- ) ?

: cellForRowAtIndexPath. : () , , () , , , , , , - .

(a), , . (b) .

:

@property(strong,nonatomic) NSMutableDictionary *images;

// initialize this when you initialize your model
self.images = [@{} mutableCopy];

// move the network code into its own method for clarity
- (void)imageWithPath:(NSString *)path completion:(void (^)(UIImage *, NSError *))completion {
    if (self.images[indexPath]) {
        return completion(self.images[indexPath], nil);
    }
    NSURL *imageURL = [NSURL URLWithString:path];
    NSURLRequest *request = [NSURLRequest requestWithURL:imageURL];
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
        if (!error){
            UIImage *image = [UIImage imageWithData:data];
            self.images[indexPath] = image;
            completion(image, nil);
        } else {
            completion(nil, error);
        }
    }];
}

, cellForRowAtIndexPath.

UIImage *image = self.images[indexPath];
if (image) {
    [cell.CellImg setBackgroundImage:image forState:UIControlStateNormal];
} else {
    // this is a good place for a placeholder image if you want one
    [cell.CellImg setBackgroundImage:nil forState:UIControlStateNormal];
    // presuming that 'img' is a string from your mode
    [self imageWithPath:img completion:^(UIImage *image, NSError *error) {
        // the image is ready, but don't assign it to the cell subview
        // just reload here, so we get the right cell for the indexPath
        [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    }];
}

, ... , . , , , indexPath.

: , , , . , . ( , ). ( iOS 5+, ), subview...

self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = // your best guess at the average height here
+2

:

cell.imageViewHeightConstraint.constant=result.width*(imgz.size.height/imgz.size.width);
[table reloadRowsAtIndexPaths:@[indexPathForCurrentCell] withRowAnimation:UITableViewRowAnimationNone];

.

0

All Articles