繁体   English   中英

奇怪的错误:UITableView中的insertRowsAtIndexPaths崩溃,并带有NSInternalInconsistencyException

[英]Strange error: insertRowsAtIndexPaths in UITableView crashes with NSInternalInconsistencyException

我已经在我编写的以下示例应用程序中找到了对NSInternalInconsistencyException的更合适答案,但仍然没有。 目标是为tableView的每个部分的第一行创建一个展开/折叠功能。 现在,我尝试实现扩展部分,该方法适用于第0部分的第0行。用户在另一部分中点击第0行后,就会出现此错误:

** 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做到了这NSMutableArray *rowsInSection以便UITableView数据源方法:

- (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

如果要同时插入/删除多行,则必须将其与对beginUpdates / endUpdates括起来。

表格视图数据源需要与您的插入/删除调用一致。 numberOfRowsInSection设置一个断点,以确保节中插入/删除行之后的行数正确。

(我不会通读所有代码来为您调试)。

祝好运!

我也有这个问题。

这不是我在代码体内做错的事情,但是我没有意识到在另一个时间将一个对象插入到我的dataSource中。 如果遇到此问题,请确保遵循bshirley的建议,并在numberOfRowsInSection和添加该项目的代码正文上放置一个断点。 确保在添加数据的整个生命周期中,该数字与dataSource中的项目数量相同。 确实没有任何理由应该失败。

这非常简单,只需确保在更新前后保持数据量和索引路径量即可。 否则将抛出此异常。

用这种方法

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

您的变量NSIndexPath *indexPath与该方法的变量重复

您不仅要插入单元格,还要删除旧行,但是表视图并不知道它,因为您没有告诉它。 因此,表视图“知道”它有一行,然后告诉您添加了两行。 该表视图知道,它应该包含3行,但是在您删除旧行时它仅会发现两行...您需要的是使用-(void)tableView:(UITableView)tableView deleteRowsAtIndexPaths:(NSArray)indexPath withRowAnimation:(UITableViewRowAnimation)animation; 或从添加的行数组中删除一个索引路径...
顺便说一句,请返回使用可重复使用的单元格,因为它与您遇到的错误没有任何关系...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM