Странная ошибка: insertRowsAtIndexPaths в UITableView аварийно завершает работу с NSInternalInconsistencyException - PullRequest
2 голосов
/ 21 сентября 2011

Я искал более подходящий ответ для NSInternalInconsistencyException, который я получил в следующем примере приложения, которое я написал, но все еще ничего.Цель состоит в том, чтобы создать функцию разворачивания / свертывания для верхней строки в каждом разделе tableView.Сейчас я пытаюсь реализовать часть расширения, и это работает для строки 0 в разделе 0. Как только пользователь нажимает строку 0 в другом разделе, появляется эта ошибка:

<code>** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Unable to resolve row for index path:  2 indexes [0, 1]'

Это странно, поскольку я сохраняю каждую UITableViewCell для таблицы в изменяемом массиве массивов.NSMutableArray *cellForRow, где каждый индекс представляет раздел в таблице, а каждый объект - объект типа NSMutableArray.Я делаю это, чтобы избежать каких-либо проблем, возникающих из очереди многократно используемых ячеек, которые, как я сначала думал, вызвали указанное выше исключение.

Исключение происходит в операторе insertRowsAtIndexPaths.Ранее я читал здесь, что код UITableViewController должен отслеживать изменения количества строк, вызванные вставками / удалениями.Я полагаю, что я делаю это с NSMutableArray *rowsInSection, чтобы метод источника данных UITableView:

<code>- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

вернулправильное количество строк в разделе после изменения.

Что я делаю неправильно в своем коде, чтобы получить вышеупомянутое исключение?


Это файл интерфейса:

#import <UIKit/UIKit.h> 
#import <QuartzCore/QuartzCore.h>

@interface MasterViewController : UITableViewController {
  NSMutableArray *rowsInSection;
  NSMutableArray *cellForRow;
}

@property (nonatomic,strong) NSMutableArray *rowsInSection;
@property (nonatomic,strong) NSMutableArray *cellForRow;

@end

И это файл реализации:

#import "MasterViewController.h"

const NSInteger numSections = 4;
const NSInteger numRows = 1 + 4;
const NSInteger addRemoveRows = 4;

@implementation MasterViewController

@synthesize rowsInSection;
@synthesize cellForRow;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

    if (self) {

        self.title = @"Table View";
        rowsInSection = [NSMutableArray arrayWithCapacity:numSections];
        cellForRow = [NSMutableArray arrayWithCapacity:numSections];
    }
    return self;
}


#pragma mark - View lifecycle

- (void)viewDidLoad {
    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    self.tableView.backgroundColor = [UIColor clearColor];
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    self.tableView.dataSource = self;
    self.tableView.delegate = self;

    // add number of rows for section
    for (NSInteger i = 0; i < numSections; i++) {
        [self.rowsInSection addObject:[NSNumber numberWithInteger:1]];
    }

    // container for reusable table view cells
    for (NSInteger i = 0; i < numSections; i++) {

        NSMutableArray *rowsArray = [NSMutableArray arrayWithCapacity:numRows];

        for (NSInteger j = 0; j < numRows; j++) {

            // top row in section
            if (j == 0) {
                UITableViewCell *topCell = [[UITableViewCell alloc] 
                                            initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
                topCell.accessoryType = UITableViewCellAccessoryNone;
                topCell.contentView.backgroundColor = [UIColor whiteColor];
                topCell.textLabel.textColor = [UIColor blueColor];
                [rowsArray addObject:topCell];

                // the rest
            } else {
                UITableViewCell *simpleCell = [[UITableViewCell alloc] 
                                               initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
                simpleCell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
                simpleCell.textLabel.textColor = [UIColor whiteColor];
                [rowsArray addObject:simpleCell];
            }
        }

        // add rows for current section into cell container
        [self.cellForRow addObject:rowsArray];
    }

}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return numSections;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    NSInteger rows = [(NSNumber *)[self.rowsInSection objectAtIndex:section] integerValue];

    //NSLog(@"%@",self.rowsInSection);
    //NSLog(@"Rows: %d in section: %d",rows,section);

    return rows;
}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    // Configure the cell.

    // row count
    NSLog(@"Rows: %d in section: %d",[tableView numberOfRowsInSection:indexPath.section],indexPath.section);


    if (indexPath.row == 0) {
        UITableViewCell *cell = (UITableViewCell *)[[self.cellForRow objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
        cell.textLabel.text = @"TOP ROW";
        NSLog(@"Row: %d in section: %d - %@",indexPath.row,indexPath.section,cell);
        return cell;
    } else {
        UITableViewCell *cell = (UITableViewCell *)[[self.cellForRow objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
        cell.textLabel.text = [NSString stringWithFormat:@"row: %d",indexPath.row];
        NSLog(@"Row: %d in section: %d - %@",indexPath.row,indexPath.section,cell);
        return cell;
    }

    // not reaching here
    return nil;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    return [NSString stringWithFormat:@"Section %d",section];
}


#pragma mark - Row editing

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    // add table view cells to section if tapped on top row
    if (indexPath.row == 0 && [tableView numberOfRowsInSection:indexPath.section] == 1) {

        //NSLog(@"Selected row: %d in section: %d",indexPath.row,indexPath.section);

        NSMutableArray *indexPathArray = [NSMutableArray array];

        for (NSInteger i = 1; i <= addRemoveRows; i++) {
            NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:indexPath.section];
            [indexPathArray addObject:indexPath];
        }

        // update row count for section
        NSInteger newRowCount = addRemoveRows + 1; // +1 for existing top row
        [self.rowsInSection replaceObjectAtIndex:indexPath.section withObject:[NSNumber numberWithInteger:newRowCount]];


        [tableView beginUpdates];
        [tableView insertRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationTop];
        [tableView endUpdates];

    }
}

@end

Ответы [ 4 ]

5 голосов
/ 21 сентября 2011

Если вы вставляете / удаляете несколько строк одновременно, необходимо заключить в скобки вызовы beginUpdates / endUpdates.

Источник данных табличного представления должен соответствовать вашей вставке /удалить звонки. Установите точку останова в numberOfRowsInSection, чтобы убедиться, что число строк в разделе правильное после вставки / удаления строк.

(я не собираюсь читать все ваш код для его отладки.)

удачи!

1 голос
/ 20 января 2012

У меня тоже была эта проблема.

Это было не то, что я делал неправильно в теле кода, но я не осознавал, что объект вставлялся в мой источник данных в другое время.Если вы получаете эту проблему, убедитесь, что вы следуете совету bshirley и прикрепите точку останова к numberOfRowsInSection И телу кода, где вы добавляете элемент.Убедитесь, что количество равно количеству элементов в вашем источнике данных на протяжении всего жизненного цикла добавления данных.На самом деле нет никаких причин, по которым он может потерпеть неудачу.

Это довольно просто, просто убедитесь, что вы сохраняете свои данные и значения indexpath до и после обновления.В противном случае это исключение будет выброшено.

0 голосов
/ 27 декабря 2013

В этом методе

-(void)tableView:(UITableView)tableView deleteRowsAtIndexPaths:(NSArray)indexPath withRowAnimation:(UITableViewRowAnimation)animation;

ваша переменная NSIndexPath *indexPath является повторением переменной этого метода

0 голосов
/ 21 сентября 2011

Вы не только вставляете ячейки, вы также удаляете старую строку, но табличное представление не знает об этом, поскольку вы этого не сказали.Таким образом, табличное представление «знает», что оно имеет одну строку, а затем вы говорите, что добавили, скажем, две строки.Табличное представление знает, что оно должно содержать 3 строки, НО оно находит только две, поскольку вы удалили старую ... Вам нужно либо использовать -(void)tableView:(UITableView)tableView deleteRowsAtIndexPaths:(NSArray)indexPath withRowAnimation:(UITableViewRowAnimation)animation;, либо удалить один путь индекса из массива добавленных строк ...
И, кстати, вернитесь к использованию повторно используемых ячеек, поскольку они не связаны с ошибкой, с которой вы столкнулись ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...