попытка вставить объект nil из объектов [0]?

21

В моем приложении у меня есть UITableView и несколько кнопок, которые пользователь может щелкнуть, чтобы отсортировать массив в порядке, основанном на некоторых NSDate или целых числах. Так что это мой метод, чтобы попытаться отсортировать мой 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, потому что казалось, что reloadData в UITableView вызывал сбой.

Вот что такое журнал сбоя консоли:

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

В любом случае, есть ли здесь какой-нибудь код, который мог бы вызвать этот сбой? Я действительно хочу, чтобы эта функциональность работала в моем приложении, и я знаю, что близок к ее исправлению, но я просто не уверен, что является причиной этой проблемы.

Есть идеи?

    
задан SimplyKiwi 13.08.2012 в 14:25
источник

2 ответа

11

Есть хотя бы одно место, где это может происходить, и, возможно, другие. В коде, где вы получаете содержимое пользовательских настроек по умолчанию, вы не проверяете 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 . Например, в вашем случае вы бы передали nil yo создаваемый вами массив, если для clickedButton.tag еще не установлено значение 1 или 2. Возможно, вы захотите добавить дополнительное условие 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");
}
    
ответ дан Tim Dean 13.08.2012 в 15:48
  • Всякий раз, когда я вызываю строку sortUsingDesriptors, он запускается только в том случае, если self.cellArray.count не равен 0. Я также исправил проблему с тегом, чтобы дескриптор был правильно инициализирован, но я все равно получаю тот же крах. Self.cellArray не равен нулю и имеет счет 2 или более (1 или менее, он не вызван моими условными выражениями). Что еще может быть проблема? –  SimplyKiwi 14.08.2012 в 05:09
  • Сложно сказать - вы должны показать нам больше полной трассировки стека, чтобы определить, где в вашем коде возникает проблема. Кроме того, вы положили чек, который я предложил убедиться, что вы получаете ненулевое значение из NSUserDefaults? –  Tim Dean 14.08.2012 в 14:52
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);

Вы также говорите, что число строк в два раза больше числа cellArray, угадайте, что это намеренно.

    
ответ дан David H 13.08.2012 в 15:25
  • Почему я должен изменить строку setObject на ваш? Что такое рассуждение, так что я понимаю логику. Кроме того, я намеренно умножаю число cellArray на 2. –  SimplyKiwi 14.08.2012 в 04:30
  • Поскольку cellArray является изменяемым, и если userDefaults просто сохраняет его и не копирует (и я точно не знаю, что он делает), то, если вы измените cellArray, он изменится на то, для тебя. –  David H 14.08.2012 в 13:13