ios - UITableView with complex cells is slow and laggy -


i've finished app , seems work main view.
it's uiviewcontroller embedded uitableview.
i'm using parse backend, , array of objects need in viewdidload method.

each cell contains data i'm fetching in tableview:cellforrowatindexpath , i'm afraid reason why table view laggy, don't know how fetch data need each object in array without having indexpath.row number.

i've made each cell element "opaque" suggested in other answers.

this code, appreciated:

- (uitableviewcell *)tableview:(uitableview *)tableview cellforrowatindexpath:(nsindexpath *)indexpath {     static nsstring *cellidentifier = @"cellht";     cellht *cell = (cellht *)[tableview dequeuereusablecellwithidentifier:cellidentifier];     if (!cell) {         cell = [[cellht alloc]                 initwithstyle:uitableviewcellstyledefault                 reuseidentifier:cellidentifier];     }      // self.hh nsarray containing objects     nsuserdefaults *prefs = [nsuserdefaults standarduserdefaults];     cell.lbltitle.text = [self.hh[indexpath.row] objectforkey:@"title"];     cell.lblvenuename.text = [self.hh[indexpath.row] objectforkey:@"venuename"];     cell.lbldistance.text = nslocalizedstring(@"distance you", nil);     self.geo = [self.hh[indexpath.row] objectforkey:@"coordinates"];      // formatters initialized in viewdidload: method     self.formatdata = [nsdateformatter dateformatfromtemplate:@"dd/mm" options:0 locale:[nslocale currentlocale]];     [self.formatterdata setdateformat:self.formatdata];     self.formatora = [nsdateformatter dateformatfromtemplate:@"j:mm" options:0 locale:[nslocale currentlocale]];     [self.formatterora setdateformat:self.formatora];     self.dal = nslocalizedstring(@"from", nil);     self.ore = nslocalizedstring(@"at", nil);     cllocation *vloc = [[cllocation alloc] initwithlatitude:self.geo.latitude longitude:self.geo.longitude];     cllocation *user = [[cllocation alloc] initwithlatitude:self.usergeo.latitude longitude:self.usergeo.longitude];     cllocationdistance distance = [user distancefromlocation:venueloc];     if ([[prefs objectforkey:@"unit"] isequaltostring:@"km"]) {         cell.lbldist.text = [nsstring stringwithformat:@"%.1f km", distance /1000];     } else {         cell.lbldist.text = [nsstring stringwithformat:@"%.1f miles", distance /1609];     }      // compare object's starting date current date set images in cell     nscomparisonresult startcompare = [[self.hh[indexpath.row] objectforkey:@"startdate"] compare: [nsdate date]];     if (startcompare == nsordereddescending) {         cell.quad.image = [uiimage imagenamed:@"no_ht"];         cell.lblstarttime.textcolor = [uicolor redcolor];     } else {         cell.quad.image = [uiimage imagenamed:@"yes_ht"];         cell.lblstarttime.textcolor = [uicolor colorwithred:104.0/255.0 green:166.0/255.0 blue:66.0/255.0 alpha:1.0];     }     nsstring *datainizio = [nsstring stringwithformat:@"%@ %@ %@ %@", self.dal, [self.formatterdata stringfromdate:[self.hh[indexpath.row] objectforkey:@"startdate"]], self.ore, [self.formatterora stringfromdate:[self.hh[indexpath.row] objectforkey:@"enddate"]]];     cell.lblstarttime.text = datainizio;     pfobject *cat = [self.hh[indexpath.row] objectforkey:@"catparent"];     nsstring *languagecode = [[nslocale preferredlanguages] objectatindex:0];     if ([languagecode isequaltostring:@"it"]) {         cell.lblcategory.text = [cat objectforkey:@"nome_it"];     } else if ([languagecode isequaltostring:@"es"]) {         cell.lblcategory.text = [cat objectforkey:@"nome_es"];     } else {         cell.lblcategory.text = [cat objectforkey:@"nome_en"];     }      //getting image data parse pffile     pffile *theimage = [self.hh[indexpath.row] objectforkey:@"photo"];     [theimage getdatainbackgroundwithblock:^(nsdata *data, nserror *error) {         if (!error) {             cell.cellimageview.image = [uiimage imagewithdata:data];         }     }];      //getting cell object's owner , profile     pfuser *usr = [self.hh[indexpath.row] objectforkey:@"parent"];     pfquery *prof = [pfquery querywithclassname:@"profile"];     prof.cachepolicy = kpfcachepolicycachethennetwork;     [prof wherekey:@"parent" equalto:usr];     [prof getfirstobjectinbackgroundwithblock:^(pfobject *object, nserror *error) {         if (!error) {             //getting object's rating , number of votes             pfquery *ratequery = [pfquery querywithclassname:@"rating"];             [ratequery wherekey:@"parent" equalto:object];             [ratequery getfirstobjectinbackgroundwithblock:^(pfobject *object, nserror *error) {                 if (!error) {                     float vote = [[object objectforkey:@"rate"] floatvalue];                     float temp = ((vote * 2) + 0.5);                     int tempvote = (int)temp;                     float roundedvote = (float)tempvote / 2;                     // drawing stars number, depending on rating obtained                     uiimage *starsimage = [uiimage imagenamed:@"stars"];                     uigraphicsbeginimagecontextwithoptions(cell.imgvoto.frame.size, no, 0);                     cgpoint starpoint = (cgpoint) {                         .y = (cell.imgvoto.frame.size.height * (2 * roundedvote + 1)) - (starsimage.size.height)                     };                     [starsimage drawatpoint:starpoint];                     cell.imgvoto.image = uigraphicsgetimagefromcurrentimagecontext();                     uigraphicsendimagecontext();                     cell.lblvoto.text = [nsstring stringwithformat:@"(%d)", [[object objectforkey:@"voters"] intvalue]];                 }             }];         }        }];     return cell; } 

edit: cell code:

+ (void)initialize {     if (self != [hh class]) {         return;     } }  -(id)initwithcoder:(nscoder *)adecoder {     if ( !(self = [super initwithcoder:adecoder]) ) return nil;      self.cellimageview.image = [uiimage imagenamed:@"icona_foto"];     self.cellimageview.contentmode = uiviewcontentmodescaletofill;     self.formatterdata = [[nsdateformatter alloc] init];     self.formatdata = [[nsstring alloc] init];     self.formatterora = [[nsdateformatter alloc] init];     self.formatora = [[nsstring alloc] init];     self.formatdata = [nsdateformatter dateformatfromtemplate:@"dd/mm" options:0 locale:[nslocale currentlocale]];     [self.formatterdata setdateformat:self.formatdata];     self.formatora = [nsdateformatter dateformatfromtemplate:@"j:mm" options:0 locale:[nslocale currentlocale]];     [self.formatterora setdateformat:self.formatora];     self.lblvoto.text = @"(0)";      return self; } 

second edit: code in viewdidload method:

        pfquery *hours = [pfquery querywithclassname:@"hh"];         hours.cachepolicy = kpfcachepolicycachethennetwork;         // here i'm making lots of query constraints i'll not include          [hours findobjectsinbackgroundwithblock:^(nsarray *objects, nserror *error) {             if (!error) {                 self.objectsnumber = objects.count;                 self.hh = [[nsarray alloc] initwitharray:objects];             }         }];         [self.tableview reloaddata]; } 

i move of logic out of cellforrowatindexpath: can, needs light-weight scrolling performance. you're doing lot of work on main thread, , lot more of work when model objects parse (if post viewdidload can give more specific help) , update table view when these calls done:

  • [uiimage imagewithdata:data]
  • anything nsdateformatter
  • cllocation's initwithlatitude:longitude:
  • creating rating stars image

none of these depend on state of table view, can precomputed , cached in model object. if scroll , down table, you're doing allo f same work on , over, killing performance.


updated questioner's newest code:

i won't include of functionality here should give idea:

// create single shared formatter instead of 1 per object nsdateformatter *dateformatter = [nsdateformatter dateformatfromtemplate:@"dd/mm" options:0 locale:[nslocale currentlocale]]; nsdateformatter *timeformatter = [nsdateformatter dateformatfromtemplate:@"j:mm" options:0 locale:[nslocale currentlocale]];  [hours findobjectsinbackgroundwithblock:^(nsarray *objects, nserror *error) {     if (!error) {         self.objectsnumber = objects.count;          (someobject *modelobj in objects) {              // if can add properties model object directly,              // otherwise write category on parse object add ones need              modelobj.datestring = [nsstring stringwithformat:@"%@ %@ %@ %@", modelobj.dal, [self.dateformatter stringfromdate:[modelobj objectforkey:@"startdate"]], modelobj.ore, [self.timeformatter stringfromdate:[modelobj objectforkey:@"enddate"]]];               // create locations, images, etc in here         }          self.hh = [[nsarray alloc] initwitharray:objects];     } }];] 

then in cellforrowatindexpath:, take precomputed properties , assign them appropriate labels, image views, etc.

it better of processing off main thread via gcd, out of scope question. see using gcd , blocks effectively more information. remember interact uikit main thread!


Comments

Popular posts from this blog

c++ - Function signature as a function template parameter -

How to call a javascript function after the page loads with a chrome extension? -

algorithm - What are some ways to combine a number of (potentially incompatible) sorted sub-sets of a total set into a (partial) ordering of the total set? -