heightForRowAtIndexPath иногда вылетает при загрузке, NSCoding - iOS

Некоторая информация о том, как я сохраняю свои данные: у меня есть массив контроллеров просмотра, которые добавляются и удаляются пользователем (в основном это приложение для создания заметок, а контроллеры просмотра — это папки). Контроллеры представления имеют несколько динамических свойств, которые приложение должно сохранить, а также массив заметок внутри них, а затем сами объекты заметок имеют несколько свойств, которые необходимо сохранить. Контроллеры представления и заметки, конечно, имеют надлежащий материал NSCoding, например, это тот, что находится на контроллере представления:

- (void) encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:self.folderName forKey:@"lvcTitle"];
    [encoder encodeObject:[NSNumber numberWithInt:self.myPosition] forKey:@"myPosition"];
    [encoder encodeObject:self.notes forKey:@"notes"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    self.folderName = [decoder decodeObjectForKey:@"lvcTitle"];
    NSNumber *gottenPosition = [decoder decodeObjectForKey:@"myPosition"];
    int gottenPositionInt = [gottenPosition intValue];
    self.myPosition = gottenPositionInt;
    self.notes = [decoder decodeObjectForKey:@"notes"];
    return self; }

Массив контроллеров принадлежит классу Singleton. NSCoding довольно сбивает меня с толку, хотя он считается простым, но до сих пор мне удавалось только сказать Singleton сохранить массив контроллеров, который затем (успешно) сохраняет все содержащиеся свойства контроллеров представления, их свойства, а также все свойства Notes. Вот код в синглтоне:

- (void) saveDataToDisk:(id)object key:(NSString *)key {
    NSString *path = [self pathForDataFile];

    NSMutableDictionary *rootObject;
    rootObject = [NSMutableDictionary dictionary];

    [rootObject setValue:object forKey:key];
    [NSKeyedArchiver archiveRootObject:rootObject toFile:path]; } 

- (void) loadDataFromDisk {
    NSString *path = [self pathForDataFile];
    NSDictionary *rootObject;

    rootObject = [NSKeyedUnarchiver unarchiveObjectWithFile:path];    

    if ([rootObject valueForKey:@"controllers"] != nil) {
        self.controllers = [NSMutableArray arrayWithArray:[rootObject valueForKey:@"controllers"]];
        firstRun = false;

        LabeledViewController *lastOneThere = [self.controllers objectAtIndex:self.controllers.count-1];
        lastOneThere.isFolderAddView = TRUE;

    }else{
        firstRun = true;
    } 
}

Затем я несколько раз вызываю метод сохранения в контроллерах просмотра папок:

[singleton saveDataToDisk];

И это будет хорошо работать несколько раз, пока я случайно не вылетаю прямо во время загрузки приложения. Виновником является heightForRowAtIndexPath:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

Note *currentNote = [self.notes objectAtIndex:indexPath.row];
if (currentNote.associatedCellIsSelected) {
    return currentNote.myHeight + NOTE_BUTTON_VIEW_HEIGHT;
}

return NORMAL_CELL_FINISHING_HEIGHT;  }

Я получаю следующую ошибку:

2012-06-07 08:28:33.694 ViewTry[1415:207] -[__NSCFString associatedCellIsSelected]: unrecognized selector sent to instance 0x8904710
2012-06-07 08:28:33.696 ViewTry[1415:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString associatedCellIsSelected]: unrecognized selector sent to instance 0x8904710'
*** First throw call stack:

Я понимаю, что «__NSCFString» и «неопознанный селектор, отправленный в экземпляр» означают, что где-то есть строка, которой не должно быть, поскольку AssociateCellIsSelected — это логическое значение. Однако, если я верну только «currentNote.myHeight» в heightForRow, я также получу ту же ошибку __NSCF с myHeight, которая является плавающей. Если я уберу heightForRow все вместе, все работает, кроме соответствующих определений высоты.

Кстати, табличное представление, на которое ссылается heightForRowAtIndexPath, создается в loadView ПОСЛЕ создания и заполнения массива заметок. Я просто не понимаю, почему эта ошибка появляется только время от времени (например, 5-10 открытий, сохранений, закрытий и повторных открытий приложения), казалось бы, случайных - я не могу найти закономерность, вызывающую такое поведение. Любые указатели?

Извините за беспорядок, я новичок в программировании iOS, и я уверен, что делаю здесь много вещей неправильно.

Изменить. Кроме того, после сбоя приложения оно остается сбойным каждый раз, когда я снова открываю его (если только я не отключу heightForRow), пока я не удалю и не переустановлю его.


person Zack    schedule 05.06.2012    source источник


Ответы (1)


Когда вы видите ошибку «неопознанный селектор» и тип получателя не соответствует типу объекта, который вы закодировали (в данном случае __NSCFString вместо Note), скорее всего, у вас возникла проблема, когда объект, который вы намеревались использовать, был преждевременно освобождается, и его адресное пространство повторно используется для размещения нового объекта.

Исправление зависит от отслеживания того, где происходит дополнительный выпуск (или не происходит сохранение). Если вы можете показать объявление @property для notes, это может пролить больше света на ситуацию.

Можно быстро выбрать «Продукт» -> «Анализ» в меню и исправить все, что он помечает. Он не поймает все, но это хорошая проверка работоспособности для начала.

person Phillip Mills    schedule 05.06.2012