Objective c 表重载数据可能导致崩溃
Crashlytics偶尔(每周一次)会报告崩溃,例如Objective c 表重载数据可能导致崩溃,objective-c,uitableview,Objective C,Uitableview,Crashlytics偶尔(每周一次)会报告崩溃,例如 Fatal Exception: NSRangeException -[__NSArrayM objectAtIndex:]: index 7 beyond bounds [0 .. 1] [MusicList tableView:heightForRowAtIndexPath:] 我想知道这些情况是否是由于在表完成渲染之前重新加载了数据造成的,所以当它请求一段数据时,它已经被删除而没有被重新插入 如果是这种情况,是否最好从viewwi
Fatal Exception: NSRangeException
-[__NSArrayM objectAtIndex:]: index 7 beyond bounds [0 .. 1]
[MusicList tableView:heightForRowAtIndexPath:]
我想知道这些情况是否是由于在表完成渲染之前重新加载了数据造成的,所以当它请求一段数据时,它已经被删除而没有被重新插入
如果是这种情况,是否最好从viewwillbeen
中删除reloadData
调用,并将其放置在viewdidebeen
中?但随后,它将显示潜在的旧数据,然后使用可能会对最终用户造成不安的新内容进行刷新
这是我迄今为止针对控制器的代码:
@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;
}
更新:从
音乐列表返回的数据
:
- (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` FROM `music` ORDER BY `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;
}
问题出在UITableView委托中,即使苹果公司没有关于该委托调用顺序的文档,您也可以通过
NSLog()查看调用顺序代码>在每个代理中
在代码中:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return [_titles[indexPath.section] isEqualToString:@"NowPlaying"] ? 100.0: 44.0;
}
依赖于另一个委托
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [_titles count];
}
此代理将告诉indexPath
有多少节,如果heightforrowtaindexpath
是在numberOfSectionsInTableView
之前首先调用的,该怎么办
另一个问题是重新加载UITableView inside-视图将出现
,我也不知道这背后的原因,但我以前遇到过这个问题,我所做的是重复检查UITableView委托中的数据源,如:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (!_titles) // just to double check if _title is allocated and avoid `[NSNull length] error`
_titles = [[NSMutableArray alloc] init];
return [_titles count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section < _data.count) // just to prevent out of bounds
return [_data[section] count];
return 0; // zero number of row in section if out of bounds
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section < _titles.count) // just to prevent out of bounds
return [_titles[indexPath.section] isEqualToString:@"NowPlaying"] ? 100.0 : 44.0;
return 0; // zero height of row in at indexPath if out of bounds
}
-(NSInteger)节数表视图:(UITableView*)表视图{
if(!\u titles)//只是为了再次检查是否分配了\u title并避免“[NSNull length]错误`
_titles=[[NSMutableArray alloc]init];
返回[_标题计数];
}
-(NSInteger)表视图:(UITableView*)表视图行数节:(NSInteger)节{
if(section<\u data.count)//只是为了防止越界
返回[_数据[段]计数];
返回0;//如果超出边界,则节中的行数为零
}
-(CGFloat)tableView:(UITableView*)表视图行高度索引路径:(NSIndexPath*)索引路径{
if(indexPath.section<\u titles.count)//只是为了防止越界
return[_titles[indexPath.section]isEqualToString:@“NowPlaying”]?100.0:44.0;
返回0;//如果超出边界,则indexPath中的行高度为零
}
这就是我从动态使用\u titles[indexPath.section]
或变量[index]
中学到的
始终检查边界以避免超出边界。。快乐,干杯 我在10日更新了代码,将数据加载移到了viewdide
功能中,现在一切都按预期进行了-虽然我们每隔几天就会收到一次崩溃报告,但在12天内还没有收到一次崩溃,所以一切都很好
通过添加一些位置良好的NSLog
,我最终能够重现错误,并且可以偶尔看到数据在所有cellForRowAtIndexPath
运行之前完成加载,因此该错误肯定不是@droppy在MusicList
传回损坏数据时建议的错误
- (void)viewDidLoad {
[super viewDidLoad];
[self setTitles:[[NSMutableArray alloc] init]];
[self setData: [[NSMutableArray alloc] init]];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear: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];
});
});
}
显示numberOfSectionsInTableView:
和表格视图:numberOfRowsInSection:
的实现。当然,已经在中添加了。好的,我看不到任何检查在加载音乐时,\u标题
和\u数据
是否有效。请添加一些断言,因为这个错误几乎肯定与数据有关。嗯,我想可能是这样的。您建议这些断言是如何做出的?您知道两者之间的关系,所以请编写代码来检查这种关系的各个方面。如果数据已损坏(如果数据在应用程序包之外,则肯定有可能),那么您不希望应用程序以这种方式崩溃。最好是清除这两个值,使表为空。无论如何,我肯定这就是你坠机的原因。