iphone - Correct way to asynchronously load tableview cell data -


i try asynchronously set uitableviewcell 'description' field, due reusing view cells have problems when fast scroll tableview - tableview cells refreshed several times. code below. what's wrong here?

   - (uitableviewcell *)tableview:(uitableview *)tableview cellforrowatindexpath:(nsindexpath *)indexpath;     {         [timeexecutiontracker starttrackingwithname:@"cellforrowatindexpath"];          static nsstring *cellidentifier = @"messagecell";          uitableviewcell *cell = [tableview dequeuereusablecellwithidentifier:cellidentifier];         if (cell == nil)         {             cell = [[uitableviewcell alloc] initwithstyle:uitableviewcellstyledefault reuseidentifier:cellidentifier];         }          ctcoremessage *message = [_searchresults objectatindex:indexpath.row];         uilabel *fromlabel = (uilabel *)[cell viewwithtag:101];         uilabel *datelabel = (uilabel *)[cell viewwithtag:102];         uilabel *subjectlabel = (uilabel *)[cell viewwithtag:103];         uilabel *descriptionlabel = (uilabel *)[cell viewwithtag:104];         [subjectlabel settext:message.subject];         [fromlabel settext:[message.from tostringseparatingbycomma]];         [datelabel settext:[nsdateformatter localizedstringfromdate:message.senderdate                                                           datestyle:nsdateformattershortstyle                                                           timestyle:nil]];           nsstring *cellhash = [[nsstring stringwithformat:@"%@%@%@",fromlabel.text,datelabel.text,subjectlabel.text] md5];          if([_tableviewdescirptions valueforkey:cellhash] == nil){              [descriptionlabel settext:@"loading ..."];              dispatch_async(backgroundqueue, ^{                  bool ishtml;                 nsstring *shortbody = [message bodypreferringplaintext:&ishtml];                 shortbody = [shortbody substringtoindex: min(100, [shortbody length])];                 [_tableviewdescirptions setvalue:shortbody forkey:cellhash];                  dispatch_async(dispatch_get_main_queue(), ^{                      [descriptionlabel settext:[_tableviewdescirptions valueforkey:cellhash]];                  });             });         }else{              [descriptionlabel settext:[_tableviewdescirptions valueforkey:cellhash]];         }           [timeexecutiontracker stoptrackingandprint];          return cell;     } 

the block

dispatch_async(dispatch_get_main_queue(), ^{     [descriptionlabel settext:[_tableviewdescirptions valueforkey:cellhash]]; }); 

captures current value of descriptionlabel , therefore, when block executed, update label if cell has been reused different index path in meantime.

you should therefore capture cell instead, , check if cell's (current) index path still equal original (captured) index path.

you should update _tableviewdescirptions on main thread, used data source.

this (not compiler tested):

dispatch_async(dispatch_get_main_queue(), ^{     [_tableviewdescirptions setvalue:shortbody forkey:cellhash];     if ([[tableview indexpathforcell:cell] isequal:indexpath]) {         uilabel *descriptionlabel = (uilabel *)[cell viewwithtag:104];         [descriptionlabel settext:[_tableviewdescirptions valueforkey:cellhash]];     } }); 

side note: primary methods get/set dictionary values objectforkey , setobject:forkey:. valueforkey: , setvalue:forkey: used key-value coding magic.


Comments

Popular posts from this blog

css - Which browser returns the correct result for getBoundingClientRect of an SVG element? -

gcc - Calling fftR4() in c from assembly -

.htaccess - Matching full URL in RewriteCond -