iOS: завершение работы приложения из-за необработанного исключения «NSRangeException»

Я просмотрел несколько тем с ошибками NSRangeException, но не нашел ответа на свой вопрос. Вот моя ошибка:

2015-08-15 17:28:43.793 UTK Recruiting[8794:254203] * Завершение работы приложения из-за необработанного исключения "NSRangeException", причина: "* -[__NSArrayI objectAtIndex:]: индекс 3 за пределами границ [0 .. 2]' *** Стек вызовов первого броска:

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

Разбирает каталог документов, помещает все файлы csv в соответствующие массивы.

- (void) refreshTable {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];

    NSArray *documentArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:nil];

    NSArray *csvFiles = [documentArray filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSString *evaluatedObject, NSDictionary *bindings) {
        return [evaluatedObject hasSuffix:@".csv"];
    }]];

    self.csvFileNames = (NSMutableArray*) csvFiles;
    self.csvFilePaths = [NSMutableArray arrayWithCapacity:[csvFiles count]];

    for (NSString *fileName in csvFiles) {
        [self.csvFilePaths addObject:[documentsDirectory stringByAppendingPathComponent:fileName]];
    }



    NSLog(@"files array %@", _csvFileNames);
    NSLog(@"files array %@", _csvFilePaths);

Это код UITableView:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    NSLog(@"count: %lu", (unsigned long)[self.csvFileNames count]);
    return [self.csvFileNames count];
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellforRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    cell.textLabel.text=[self.csvFileNames objectAtIndex:indexPath.row];

    return cell;
}

После размещения точек останова в моем коде я обнаружил, что он дает сбой в методе cellForRowAtIndexPath, который является последним методом в опубликованном коде. Метод cellForRowAtIndexPath вообще не запускается. Еще важно отметить, что есть 4 файла csv, и [self.csvFileNames count] правильно дает число 4.

Код должен работать до индекса 3, но я не могу понять, почему это не так.

bt все отчеты о сбоях:

  • нить # 1: TID = 0x56469, 0x0000000109200286> libsystem_kernel.dylib_7 ___ pthread_kill + 10 кадр # 1: 0x000000010923342f libsystem_pthread.dylibpthread_kill + 90 frame #2: 0x0000000108fa019a libsystem_sim_c.dylibabort + 129 кадр # 3: 0x0000000108d8b481 Libc ++ abi.dylibabort_message + 257 frame #4: 0x0000000108db33d5 libc++abi.dylibdefault_terminate_handler () + 267 кадр # 5: 0x0000000101e4be19 libobjc.A.dylib_objc_terminate() + 103 frame #6: 0x0000000108db0b01 libc++abi.dylibstd ::__terminate(void (*)()) + 8 кадров #7: 0x0000000108db07aa libc++abi.dylib__cxa_rethrow + 99 frame #8: 0x0000000101e4bd2c libobjc.A.dylibobjc_exception_rethrow + 40 кадров #9: 0x00000001020db41e CoreFoundationCFRunLoopRunSpecific + 654 frame #10: 0x0000000104e74a3e GraphicsServicesGSEventRunModal + 161 кадр #11: 0x00005ab`000102

    • frame #12: 0x000000010176311f UTK Recruitingmain(argc=1, argv=0x00007fff5e4a04f8) + 111 at main.m:14 frame #13: 0x0000000108ef8145 libdyld.dylibstart + 1 frame #14: 0x0000000108ef8145 libdyld.dylib`start + 1

    поток №2: tid = 0x564a0, 0x0000000109201232 libsystem_kernel.dylibkevent64 + 10, queue = 'com.apple.libdispatch-manager' frame #0: 0x0000000109201232 libsystem_kernel.dylibkevent64 + 10 кадр №1: 0x0000000108eb376c libdispatch.dylib_dispatch_mgr_invoke + 247 frame #2: 0x0000000108eb3511 libdispatch.dylib_dispatch_mgr_thread + 54

    поток №3: tid = 0x564a2, 0x000000010920094a libsystem_kernel.dylib__workq_kernreturn + 10 frame #0: 0x000000010920094a libsystem_kernel.dylib__workq_kernreturn + 10 кадр №1: 0x00000001092316c3 libsystem_pthread.dylib_pthread_wqthread + 869 frame #2: 0x000000010922f40d libsystem_pthread.dylibstart_wqthread + 13

    поток №4: tid = 0x564a3, 0x000000010920094a libsystem_kernel.dylib__workq_kernreturn + 10 frame #0: 0x000000010920094a libsystem_kernel.dylib__workq_kernreturn + 10 кадр №1: 0x00000001092316c3 libsystem_pthread.dylib_pthread_wqthread + 869 frame #2: 0x000000010922f40d libsystem_pthread.dylibstart_wqthread + 13

    поток № 5: tid = 0x564a4, 0x000000010920094a libsystem_kernel.dylib__workq_kernreturn + 10 frame #0: 0x000000010920094a libsystem_kernel.dylib__workq_kernreturn + 10 кадр № 1: 0x00000001092316c3 libsystem_pthread.dylib_pthread_wqthread + 869 frame #2: 0x000000010922f40d libsystem_pthread.dylibstart_wqthread + 13

    поток №6: tid = 0x564a5, 0x000000010920094a libsystem_kernel.dylib__workq_kernreturn + 10 frame #0: 0x000000010920094a libsystem_kernel.dylib__workq_kernreturn + 10 кадр №1: 0x00000001092316c3 libsystem_pthread.dylib_pthread_wqthread + 869 frame #2: 0x000000010922f40d libsystem_pthread.dylibstart_wqthread + 13

Сбой в main.m в операторе return:

int main(int argc, char * argv[]) {
@autoreleasepool {
    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

ОБНОВЛЕНИЕ: я просматривал многие другие потоки NSRangeException, но пока безуспешно.


person Alex Cauthen    schedule 19.08.2015    source источник
comment
Чтобы увидеть фактический оператор, вызывающий ошибку, добавьте точку останова исключения: 1. В главном меню Отладка:Точки останова:Создать точку останова исключения. 2. Щелкните правой кнопкой мыши точку останова и установите для исключения значение Objective-C. 3. Добавьте действие: po $arg1. Запустите приложение, чтобы получить точку останова, и вы окажетесь в строке, которая вызывает исключение, а сообщение об ошибке появится в консоли отладчика.   -  person zaph    schedule 19.08.2015
comment
Вы звоните [self.tableView reloadData] после редактирования csvFileNames?   -  person Brian Nickel♦    schedule 19.08.2015
comment
И вы меняете только csvFileNames в основном потоке?   -  person Brian Nickel♦    schedule 19.08.2015
comment
@zaph, который не дает мне номер строки. Вот что выводится в консоли отладчика: *** -[__NSArrayI objectAtIndex:]: индекс 3 за пределами [0 .. 2]   -  person Alex Cauthen    schedule 19.08.2015
comment
@ Брайан Я не вызываю это после того, как редактирую данные в csvFileNames. Где именно я должен разместить этот оператор, refreshTable или в одном из методов TableView? Единственное место, где он редактируется, — это метод refreshTable. Метод refreshTable выполняется в основном потоке.   -  person Alex Cauthen    schedule 19.08.2015
comment
Изменяет ли что-нибудь добавление reloadData после установки csvFileNames? Есть ли где-нибудь, где вы делаете [self.csvFileNames removeObject:]?   -  person Brian Nickel♦    schedule 19.08.2015
comment
Я никогда ничего не удаляю из csvFileNames. Его можно добавить только технически. Я добавил оператор reloadData после того, как csvFileNames загружается с содержимым csvFiles в методе refreshTable. Возможно, это не то место, чтобы добавить его. Это привело к сбою программы в строке, в которой был добавлен оператор reloadData.   -  person Alex Cauthen    schedule 19.08.2015


Ответы (2)


Если вы думаете, что это из UITableView, он не будет вызывать из потоков, он всегда вызывается только из основного потока. Попробуйте добавить в проект Exceptional Breakpoint, как показано на скриншоте, чтобы он остановился прямо перед тем, как произойдет сбой. Вы можете найти строку сбоя и определить, где именно возникает проблема.

Добавить исключительную точку останова

person Sumanth    schedule 19.08.2015
comment
Пишет, что происходит сбой в main. m в следующей строке: return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); Я обновлю исходный пост нового кода - person Alex Cauthen; 19.08.2015

Конечно, он вылетает из основного потока - это неперехваченное исключение. Добавление точки останова для всех исключений должно выделять [self.csvFileNames objectAtIndex:indexPath.row].

Система свойств iOS никогда не дает сбоев.

Единственное объяснение, которое я могу придумать, это то, что ваш массив обнуляется/модифицируется, пока представление таблицы заполняется.

Проверьте, как часто и откуда вызывается метод refreshTable. Это должно быть один раз.

Также не повредит поместить NSLog в tableView:cellforRowAtIndexPath: и проверить, что массив не изменяется во время выполнения.

другим, но необычным и, вероятно, маловероятным объяснением может быть модифицированный класс NSArray. (например, Категория для NSArray, которая изменяет поведение objectAtIndex:. Когда-то была обычным явлением. Но вы должны знать, добавили ли вы какие-либо категории NSArray/NSMutableArray.

Заменой вызова метода может быть индекс с ключом.

cell.textLabel.text = self.csvFileNames[indexPath.row];

person Helge Becker    schedule 20.08.2015