尝试从objects[0]插入空对象?

26
在我的应用程序中,我有一个UITableView和一些按钮,用户可以点击这些按钮来根据一些NSDate或ints对数组进行排序。因此,这是我尝试对UITableView进行排序的方法:
- (void)sortStats:(id)sender reloadData:(BOOL)dataBool {
    NSSortDescriptor *descriptor = nil;
    UIButton *clickedButton = (UIButton*)sender;
    if (clickedButton.tag == 1) {
            descriptor = [NSSortDescriptor sortDescriptorWithKey:@"Date" ascending:NO];
    }
    [self.cellArray sortUsingDescriptors:[NSArray arrayWithObject:descriptor]];
    [[NSUserDefaults standardUserDefaults] setObject:self.cellArray forKey:@"cellArray"];
    if (dataBool) {
        [ivstatstableView reloadData];
    }
    [ivstatstableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
}

原本我只有这个方法,没有reloadData参数,因为似乎UITableView上的reloadData会导致崩溃。

这是控制台崩溃日志:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]'

无论如何,这里是否有任何代码会导致崩溃? 我真的想让我的应用程序中的此功能正常工作,我知道我快要修复它了,但我不确定是什么原因导致了这个问题。

有什么想法吗?

2个回答

14

这种情况至少会发生在一个地方,也可能会发生在其他地方。在获取用户默认设置的内容的代码中,您没有检查是否为nil。所以,应该改为:

[self.cellArray addObjectsFromArray:[[NSUserDefaults standardUserDefaults] objectForKey:@"array"]];

你可以尝试这个:
NSArray *defaultCellArray = [[NSUserDefaults standardUserDefaults] objectForKey:@"array"];
if (defaultCellArray) {
    [self.cellArray addObjectsFromArray:defaultCellArray];
}

根据您的错误信息,initWithObjects调用失败的可能性也是有的,而且它可能嵌套在另一个调用中,也许就是这个调用:

[self.cellArray sortUsingDescriptors:[NSArray arrayWithObject:descriptor]];

如果您查看完整的调用堆栈,它会告诉您此调用是否在对initWithObjects进行后续调用并可能将其传递给nil。例如,在您的情况下,如果clickedButton.tag尚未设置为1或2的值,则会向您创建的数组传递一个nil。您可能需要添加额外的else子句来帮助诊断问题:

if (clickedButton.tag == 1) {
        descriptor = [NSSortDescriptor sortDescriptorWithKey:@"Date" ascending:NO];
} else if (clickedButton.tag == 2) {
        descriptor = [NSSortDescriptor sortDescriptorWithKey:@"Score" ascending:NO];
} else {
    NSLog(@"Unexpected error: Can't determine sort descriptor");
}

每当我调用sortUsingDesriptors这一行时,只有在self.cellArray.count不等于0时才会执行。我还修复了标签问题,以便正确初始化描述符,但仍然遇到相同的崩溃。self.cellArray不是nil,并且它的计数大于等于2(小于等于1时不满足我的条件)。问题可能还有其他原因吗? - SimplyKiwi
很难说 - 你应该展示更多完整的堆栈跟踪信息,以确定问题源自代码的哪个部分。另外,你是否加入了我建议的检查,以确保从NSUserDefaults返回的值不为空? - Tim Dean

2

这一切都很复杂,但有一件事情很明显:

[[NSUserDefaults standardUserDefaults] setObject:self.cellArray 
                                          forKey:@"cellArray"];

我认为你应该改成这样:

NSArray *array = [NSArray arrayWithArray:self.cellArray];
[[NSUserDefaults standardUserDefaults] setObject:array forKey:@"cellArray"];

其次,在您认为应该有对象的每个位置后添加asserts(),例如:
UIButton *theButton = ...
assert(theButton);

您还说行数是单元格数组数量的两倍,我猜这是有意为之的。

为什么我要将setObject行更改为您的行?这样做的推理是什么,以便我理解逻辑。同时,我故意将cellArray计数乘以2。 - SimplyKiwi
因为cellArray是可变的,如果userDefaults只是保留它而不复制它(我不确定它是否这样做),那么如果你改变cellArray,它将会在userDefaults所持有的副本中发生改变。 - David H

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接