ios - Loading images asynchronously in UITableView with Autolayout -


i have uitableview loads images asynchronously in uitableview. images different heights, set height constraint according height of image.

this works fine when use datawithcontentsofurl, freezes ui. when load asynchronously, images pile on top of each other so:

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

the code i'm using 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 scroll , down few times images correctly position themselves.

the question doesn't specify desired behavior varying image sizes. should cell taller fit, or image view (what looks button code) within cell?

but should put aside problem moment , work on more serious problem code: issues unguarded network request cellforrowatindexpath. result, (a) user scrolling , forth generate many many redundant requests, , (b) user scrolling long way generate request that's fulfilled when cell started gone - reused cell row.

to address (a), datasource should cache fetched images, , request haven't been received. address (b), completion block shouldn't refer directly cell.

a simple cache this:

@property(strong,nonatomic) nsmutabledictionary *images;  // initialize when initialize model self.images = [@{} mutablecopy];  // move network code own method 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);         }     }]; } 

now, fix multiple request problem checking first image in cache in cellforrowatindexpath.

uiimage *image = self.images[indexpath]; if (image) {     [cell.cellimg setbackgroundimage:image forstate:uicontrolstatenormal]; } else {     // place placeholder image if want 1     [cell.cellimg setbackgroundimage:nil forstate:uicontrolstatenormal];     // presuming 'img' string mode     [self imagewithpath:img completion:^(uiimage *image, nserror *error) {         // image ready, don't assign cell's subview         // reload here, right cell indexpath         [tableview reloadrowsatindexpaths:@[indexpath] withrowanimation:uitableviewrowanimationautomatic];     }]; } 

also notice isn't done in completion block... we're fixing cell reuse not referring cell. instead, knowing image cached, reload indexpath.

back image sizing: apps see table view cell taller or shorter along variable height subview. if that's case, should not place height constraint on subview @ all. instead, constrain it's top , bottom edges cell's content view (or include in chain of subviews constrain each other top , bottom , contain topmost , bottommost subviews top , bottom edge cell). (in ios 5+, think), allow cell change hight subview constraint chain...

self.tableview.rowheight = uitableviewautomaticdimension; self.tableview.estimatedrowheight = // best guess @ average height here 

Comments

Popular posts from this blog

dns - How To Use Custom Nameserver On Free Cloudflare? -

python - Pygame screen.blit not working -

c# - Web API response xml language -