objective c - Table reloadData can cause crashes -
very (once week'ish) crashlytics reporting crashes such
fatal exception: nsrangeexception -[__nsarraym objectatindex:]: index 7 beyond bounds [0 .. 1] [musiclist tableview:heightforrowatindexpath:]
i'm wondering if these occurring due data being reloaded before table finishes rendering, when requests piece of data has been removed , not yet been re-inserted?
if case, best remove reloaddata
call viewwillappear
, place in viewdidappear
? displaying potentially old data, refreshing newer content might jarring end user.
this code far controller:
@implementation musiclist - (void)viewdidload { [super viewdidload]; [self settitles:[[nsmutablearray alloc] init]]; [self setdata: [[nsmutablearray alloc] init]]; } - (void)viewwillappear:(bool)animated { [super viewwillappear:animated]; dispatch_queue_t loadmusic = dispatch_queue_create("loadmusic", null); dispatch_async(loadmusic, ^{ nsmutabledictionary * data = [music getmusiclist]; [self settitles:[data objectforkey:@"titles"]]; [self setdata: [data objectforkey:@"tracks"]]; dispatch_async(dispatch_get_main_queue(), ^{ [tablemusiclist reloaddata]; }); }); } - (nsinteger)numberofsectionsintableview:(uitableview *)tableview { return [_titles count]; } - (nsinteger)tableview:(uitableview *)tableview numberofrowsinsection:(nsinteger)section { return [_data[section] count]; } - (cgfloat)tableview:(uitableview *)tableview heightforrowatindexpath:(nsindexpath *)indexpath { return [_titles[indexpath.section] isequaltostring:@"nowplaying"] ? 100.0 : 44.0; }
update: data returned musiclist
:
- (nsmutabledictionary *)getmusiclist { db * db = [[db alloc] init]; nsmutabledictionary * data = [[nsmutabledictionary alloc] init]; [data setobject:[[nsmutablearray alloc] init] forkey:@"titles"]; [data setobject:[[nsmutablearray alloc] init] forkey:@"tracks"]; if ([db prepare:@"select `date`, `name` `music` order `date` desc limit 25"]) { nsstring * date; nsstring * name; while ([db stepthrough]) { date = [db get:0]; name = [db get:1]; if (date && name) { [[data objectforkey:@"titles"] addobject:date]; [[data objectforkey:@"tracks"] addobject:name]; } } } return data; }
the problem inside uitableview delegates, though apple don't have documentation order of calls delegate can check , see nslog();
in every delegate..
in code:
- (cgfloat)tableview:(uitableview *)tableview heightforrowatindexpath:(nsindexpath *)indexpath { return [_titles[indexpath.section] isequaltostring:@"nowplaying"] ? 100.0: 44.0; }
is dependent delegate
- (nsinteger)numberofsectionsintableview:(uitableview *)tableview { return [_titles count]; }
this delegate tell indexpath
how many section there, if heightforrowatindexpath
called first before numberofsectionsintableview
??
another, reloading uitableview inside -viewwillappear
, dont know reason behind had problem before , did double checking datasource inside uitableviewdelegates like:
- (nsinteger)numberofsectionsintableview:(uitableview *)tableview { if (!_titles) // double check if _title allocated , avoid `[nsnull length] error` _titles = [[nsmutablearray alloc] init]; return [_titles count]; } - (nsinteger)tableview:(uitableview *)tableview numberofrowsinsection:(nsinteger)section { if (section < _data.count) // prevent out of bounds return [_data[section] count]; return 0; // 0 number of row in section if out of bounds } - (cgfloat)tableview:(uitableview *)tableview heightforrowatindexpath:(nsindexpath *)indexpath { if (indexpath.section < _titles.count) // prevent out of bounds return [_titles[indexpath.section] isequaltostring:@"nowplaying"] ? 100.0 : 44.0; return 0; // 0 height of row in @ indexpath if out of bounds }
that's i've learn using _titles[indexpath.section]
or variable[index]
in dynamic kind of way,
always check bounds avoid out of it(bounds).. happy coding, cheers!
Comments
Post a Comment