Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 表重载数据可能导致崩溃_Objective C_Uitableview - Fatal编程技术网

Objective c 表重载数据可能导致崩溃

Objective c 表重载数据可能导致崩溃,objective-c,uitableview,Objective C,Uitableview,Crashlytics偶尔(每周一次)会报告崩溃,例如 Fatal Exception: NSRangeException -[__NSArrayM objectAtIndex:]: index 7 beyond bounds [0 .. 1] [MusicList tableView:heightForRowAtIndexPath:] 我想知道这些情况是否是由于在表完成渲染之前重新加载了数据造成的,所以当它请求一段数据时,它已经被删除而没有被重新插入 如果是这种情况,是否最好从viewwi

Crashlytics偶尔(每周一次)会报告崩溃,例如

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数据
是否有效。请添加一些断言,因为这个错误几乎肯定与数据有关。嗯,我想可能是这样的。您建议这些断言是如何做出的?您知道两者之间的关系,所以请编写代码来检查这种关系的各个方面。如果数据已损坏(如果数据在应用程序包之外,则肯定有可能),那么您不希望应用程序以这种方式崩溃。最好是清除这两个值,使表为空。无论如何,我肯定这就是你坠机的原因。