NSRangeException в TableView с разделами [indexPath Row] выходит за пределы диапазона

Вот ошибка, распечатанная на консоли:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** 
-[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 1]'
*** First throw call stack:
(0x27f0012 0x1a51e7e 0x27a5b44 0xde6d 0xe2f8fb 0xe2f9cf 0xe181bb 0xe28b4b 0xdc52dd 0x1a656b0 0x97efc0 0x97333c 0x973150 0x8f10bc 0x8f2227 0x99c333 0x99c75f 0x27af376 0x27aee06 0x2796a82 0x2795f44 0x2795e1b 0x22677e3 0x2267668 0xd74ffc 0x258d 0x24b5 0x1)
libc++abi.dylib: terminate called throwing an exception

Программа ломается ровно в:

NSString *cellValue = [models objectAtIndex:indexPath.row];

внутри cellForRowAtIndexPath: метод

Вот все методы tableview:

//---set the title for each section---
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {


     //countyIndex returns the number of counties per state
     //in the debugger I checked and the countyIndex is returning the correct number
     //of counties!
    return [countyIndex objectAtIndex:section];

}

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return [countyIndex count];
}

//---set the number of rows in each section---
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    //---get the county in section---
    NSString *county = [countyIndex objectAtIndex:section];

    //---get all models from the county---
    NSPredicate *predicate = 
    [NSPredicate predicateWithFormat:@"countyName == %@", county];
    NSArray *mods = [modelArray filteredArrayUsingPredicate:predicate];

    //---return the number of models from the county---
    return [mods count];    

}
   //models appears to be counted as the number of objects per section


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {

        cell = [[UITableViewCell alloc]
                initWithStyle:UITableViewCellStyleDefault
                reuseIdentifier:CellIdentifier];

    }

    // now configure the cell


    //---get the county in the current section---
    NSString *county = [countyIndex objectAtIndex:[indexPath section]];

    //---get all models from the county---
    NSPredicate *predicate = 
    [NSPredicate predicateWithFormat:@"countyName == %@", county];
    NSArray *mods = [modelArray filteredArrayUsingPredicate:predicate];
    NSMutableArray *newModelArray = [[NSMutableArray alloc] init];
     for (NSManagedObject *obj in mods) {
         [newModelArray addObject:[NSString stringWithFormat:@"%@",[obj valueForKey: @"model"]]];
     }


    //get rid of duplicates
    NSArray *objectsWithDuplicates = newModelArray;
    NSSet *duplicatesRemover = [NSSet setWithArray:objectsWithDuplicates];
    models = [duplicatesRemover allObjects];
    models = [models sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];


    UITableViewCell *bgView = [[UITableViewCell alloc] initWithFrame:CGRectZero];

    //cell.contentView.backgroundColor = [UIColor whiteColor];
    bgView.backgroundColor = [UIColor whiteColor];

    cell.backgroundView = bgView;
    cell.layer.borderColor = [[UIColor lightGrayColor] CGColor];      
    cell.layer.borderWidth  = .50;



    if ([models count]>0) {
        //---extract the relevant model from the model object---
        NSString *cellValue = [models objectAtIndex:indexPath.row];
        cell.textLabel.text = cellValue;

        [cell setAccessibilityTraits:UIAccessibilityTraitButton];

    }
    return cell;
}

-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    //index path to row that's selected 
    NSIndexPath *myIndexPath = [self.sTable indexPathForSelectedRow];
    UITableViewCell *cell = [self.sTable cellForRowAtIndexPath:myIndexPath];
    labelText = cell.textLabel.text;
    selectedModel = cell.textLabel.text;

}

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

ПО [количество моделей]

po (int) [строка indexPath]

Я вижу, что происходит разрыв, когда [количество моделей] равно 2, а строка [indexPath] также равно 2, что, конечно, сделает его вне диапазона, потому что 2 на самом деле равно 3, так как индексы таблицы начинаются с 0.

Вопрос в том, почему это происходит? Я уже перезагружаю tabledata после переключения значений таблицы, и я прошел и посчитал все количество строк на раздел, и они кажутся правильными. так почему еще это может происходить? Странно то, что этот разрыв происходит после cellForRowAtIndexPath:(NSIndexPath *)indexPath вызывается повторно, когда я прокручиваю таблицу вниз.

Это происходит во всех симуляторах ios 5.0 - ios 6.1 в Xcode 4.6.1

**РЕДАКТИРОВАТЬ:

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

1 ответ

Это потому, что в cellForRowAtIndexPath Вы удаляете дубликаты. Но вы не делаете это в numberOfRows, Следовательно, массив моделей в cellForRow короче, чем подсчет, полученный в numberOfRows,

Это типичный случай того, почему СУХОЕ является таким важным правилом: не повторяйте себя. Делая одно и то же в двух разных методах, вы не только тратите впустую код и усложняете его обслуживание, но и рискуете сделать то же самое по- разному в этих двух местах. Вы должны выделить код, который выводит фактическую модель для конкретного раздела (округа), чтобы был только один метод, к которому обращаются ваши два других метода. (Еще лучше было бы подготовить лучшую модель, возможно, такую, в которой всегда есть просто однозначное соответствие между строками и индексами массива.)

Другие вопросы по тегам