Столбец падает при перемещении более половины ячеек в другой раздел

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

Ошибка: * Завершение приложения из-за неперехваченного исключения 'NSRangeException', причина: '* - [__ NSArrayM objectAtIndex:]: индекс 9 за пределами границ [0.. 8]'

Метод CheckMarkTapped (вызов для переключения элемента):

-(void)checkMarkTapped:(UIButton *)sender {

    UITableViewCell *cell = ((UITableViewCell *)[sender superview]);
    NSIndexPath *originIndexPath = [self.tableView indexPathForCell:cell];
    NSIndexPath *destinationIndexPath;

    NSLog(@"originIndexPath row: %i, section: %i", originIndexPath.row, originIndexPath.section);

    [self fixAllCheckboxes];

    if (originIndexPath.section == 0) {

        destinationIndexPath = [NSIndexPath indexPathForRow:[completedItems count] inSection:1];
        [sender setSelected:NO];

        NSMutableDictionary *tempDict = [[NSDictionary dictionaryWithDictionary:[uncompletedItems objectAtIndex:originIndexPath.row]]mutableCopy];
        [completedItems addObject:tempDict];
        [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObjects:destinationIndexPath, nil] withRowAnimation:UITableViewRowAnimationLeft];
        [uncompletedItems removeObjectAtIndex:originIndexPath.row];


    }

    if (originIndexPath.section == 1) { //if the checkbox is in section 1
        [sender setSelected:YES];

        NSMutableDictionary *tempDict = [NSDictionary dictionaryWithDictionary:[[completedItems objectAtIndex:originIndexPath.row]mutableCopy]];

        destinationIndexPath = [NSIndexPath indexPathForRow:[[tempDict objectForKey:@"index"]intValue] inSection:0];
        [uncompletedItems insertObject:tempDict atIndex:[[tempDict objectForKey:@"index"]intValue]];
        [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObjects:destinationIndexPath, nil] withRowAnimation:UITableViewRowAnimationLeft];
        [completedItems removeObjectAtIndex:[self.tableView indexPathForCell:cell].row];

    }

    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:originIndexPath, nil] withRowAnimation:UITableViewRowAnimationLeft];
}

Метод CELLFORROWATINDEXPATH:

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

    static NSString *CellIdentifier = @"Cell";

    if (indexPath.section == 1) {
        CellIdentifier = @"Cell1";
    }

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        cell.showsReorderControl = YES;
    }

    for (UIControl *checkbox in [cell subviews]) {
        if (checkbox.tag == 9001) {
            [checkbox removeFromSuperview];
        }
    }

    if (indexPath.section == 0) {
        UIButton *checkbox = [[UIButton alloc]initWithFrame:CGRectMake(5, 5, 40, 40)];
        [checkbox addTarget:self action:@selector(checkMarkTapped:) forControlEvents:UIControlEventTouchUpInside];
        [cell setIndentationWidth:45];
        [cell setIndentationLevel:1];

        [checkbox setTag:9001];
        [checkbox setImage:[UIImage imageNamed:@"unchecked"] forState:UIControlStateNormal];
        [checkbox setImage:[UIImage imageNamed:@"checked"] forState:UIControlStateSelected];

        [cell addSubview:checkbox];

        cell.textLabel.backgroundColor = [UIColor whiteColor];
        cell.textLabel.backgroundColor = [UIColor whiteColor];
        cell.contentView.backgroundColor = [UIColor whiteColor];
        cell.textLabel.font = [UIFont boldSystemFontOfSize:20];

        switch (indexPath.section) {
            case 0:
                cell.textLabel.text = [[uncompletedItems objectAtIndex:indexPath.row]objectForKey:@"Name"];
                break;
            case 1:
                cell.textLabel.text = [[completedItems objectAtIndex:indexPath.row]objectForKey:@"Name"];
                [checkbox setSelected:YES];
                break;
            default:
                break;
        }

        [cell addSubview:checkbox];

    } else if (indexPath.section == 1) {

        UIButton *checkbox = [[UIButton alloc]initWithFrame:CGRectMake(5, 5, 40, 40)];
        [checkbox addTarget:self action:@selector(checkMarkTapped:) forControlEvents:UIControlEventTouchUpInside];
        [cell setIndentationWidth:45];
        [cell setIndentationLevel:1];
        [checkbox setTag:9001];

        cell.textLabel.backgroundColor = [UIColor whiteColor];
        cell.textLabel.backgroundColor = [UIColor whiteColor];
        cell.contentView.backgroundColor = [UIColor whiteColor];
        cell.textLabel.font = [UIFont boldSystemFontOfSize:20];
        cell.textLabel.text = [[uncompletedItems objectAtIndex:indexPath.row]objectForKey:@"Name"];

        [checkbox setImage:[UIImage imageNamed:@"unchecked"] forState:UIControlStateNormal];
        [checkbox setImage:[UIImage imageNamed:@"checked"] forState:UIControlStateSelected];

        [cell addSubview:checkbox];

        switch (indexPath.section) {
            case 0:
                cell.textLabel.text = [[uncompletedItems objectAtIndex:indexPath.row]objectForKey:@"Name"];
                break;
            case 1:
                cell.textLabel.text = [[completedItems objectAtIndex:indexPath.row]objectForKey:@"Name"];
                [checkbox setSelected:YES];
                break;
            default:
                break;
        }

        [cell addSubview:checkbox];
    }
    return cell;
}

Вот NSLog для Crash. Как вы можете видеть, это происходит, когда массивы имеют одинаковое количество элементов:

2012-12-26 12:54:44.583 Checklist R4[1128:c07] Destination Row: 0, UnCompleted Count: 19, Completed Count: 1
2012-12-26 12:54:45.034 Checklist R4[1128:c07] Destination Row: 1, UnCompleted Count: 18, Completed Count: 2
2012-12-26 12:54:45.454 Checklist R4[1128:c07] Destination Row: 2, UnCompleted Count: 17, Completed Count: 3
2012-12-26 12:54:45.873 Checklist R4[1128:c07] Destination Row: 3, UnCompleted Count: 16, Completed Count: 4
2012-12-26 12:54:46.294 Checklist R4[1128:c07] Destination Row: 4, UnCompleted Count: 15, Completed Count: 5
2012-12-26 12:54:47.072 Checklist R4[1128:c07] Destination Row: 5, UnCompleted Count: 14, Completed Count: 6
2012-12-26 12:54:47.399 Checklist R4[1128:c07] Destination Row: 6, UnCompleted Count: 13, Completed Count: 7
2012-12-26 12:54:48.085 Checklist R4[1128:c07] Destination Row: 7, UnCompleted Count: 12, Completed Count: 8
2012-12-26 12:54:48.621 Checklist R4[1128:c07] Destination Row: 8, UnCompleted Count: 11, Completed Count: 9
2012-12-26 12:54:49.090 Checklist R4[1128:c07] Destination Row: 9, UnCompleted Count: 10, Completed Count: 10
2012-12-26 12:54:50.234 Checklist R4[1128:c07] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 9 beyond bounds [0 .. 8]'

Ответ 1

ваш массив completedItems или uncompletedItems, один из которых имеет только 8 элементов, но вы пытаетесь получить доступ к элементу больше, чем это. Проверьте свой метод numberOfRowsInSection, укажите их динамическое значение, например

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    int rowCount = 0;
    if (section == 0) {
        rowCount = [uncompletedItems count];
    } else {
        rowCount = [completedItems count];
    }
    return rowCount;
}

и, кроме того, ему не нужны как switch, так и if. Используйте кого-нибудь, чтобы проверить ваш section на 0 или 1.

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

static NSString *CellIdentifier = @"Cell";

if (indexPath.section == 1) {
    CellIdentifier = @"Cell1";
}

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    cell.showsReorderControl = YES;
}

for (UIControl *checkbox in [cell subviews]) {
    if (checkbox.tag == 9001) {
        [checkbox removeFromSuperview];
    }
}

    UIButton *checkbox = [[UIButton alloc]initWithFrame:CGRectMake(5, 5, 40, 40)];
    [checkbox addTarget:self action:@selector(checkMarkTapped:) forControlEvents:UIControlEventTouchUpInside];
    [cell setIndentationWidth:45];
    [cell setIndentationLevel:1];

    [checkbox setTag:9001];
    [checkbox setImage:[UIImage imageNamed:@"unchecked"] forState:UIControlStateNormal];
    [checkbox setImage:[UIImage imageNamed:@"checked"] forState:UIControlStateSelected];

    [cell addSubview:checkbox];

    cell.textLabel.backgroundColor = [UIColor whiteColor];
    cell.textLabel.backgroundColor = [UIColor whiteColor];
    cell.contentView.backgroundColor = [UIColor whiteColor];
    cell.textLabel.font = [UIFont boldSystemFontOfSize:20];

    switch (indexPath.section) {
        case 0:
            cell.textLabel.text = [[uncompletedItems objectAtIndex:indexPath.row]objectForKey:@"Name"];
            break;
        case 1:
            cell.textLabel.text = [[completedItems objectAtIndex:indexPath.row]objectForKey:@"Name"];
            [checkbox setSelected:YES];
            break;
        default:
            break;
    }

    [cell addSubview:checkbox];

return cell;
}

Ответ 2

В вашем коде могут быть две проблемы.

  • You are returning numbers of rows to Table View less then your array count.
  • Your array is exceeding from the numbers of rows in Table View.

В приведенном ниже описании error ясно показано, что ваш массив имеет индексы 8, но вы обращаетесь к 9th, который вызывает ошибку.