在UITableView中插入项目会导致应用程序崩溃

时间:2014-03-02 23:10:30

标签: ios iphone objective-c uitableview

我正在创建一个带有联系人的tableview列表的应用程序,可以通过底部的选项卡控制器访问这些联系人。

我从示例主详细信息应用程序中复制(字面上复制/粘贴)并尝试确保所有故事板引用都排成一行。

#import "ContactsTableViewController.h"

#import "ContactViewController.h"

@interface ContactsTableViewController () {
    NSMutableArray *_objects;
}

@end

@implementation ContactsTableViewController

- (void)awakeFromNib
{
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
        self.clearsSelectionOnViewWillAppear = NO;
        self.preferredContentSize = CGSizeMake(320.0, 600.0);
    }
    [super awakeFromNib];

//    [self.tableView setDelegate:self]; // From (unsuccesfully) trying https://stackoverflow.com/questions/16311393/how-to-insert-items-to-a-uitableview-when-a-uibutton-is-clicked-in-ios
//    [self.tableView setDataSource:self];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.navigationItem.leftBarButtonItem = self.editButtonItem;

    UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)];
    self.navigationItem.rightBarButtonItem = addButton;
    self.contactViewController = (ContactViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];    
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)insertNewObject:(id)sender
{
    if (!_objects) {
        _objects = [[NSMutableArray alloc] init];
    }
    [_objects insertObject:[NSDate date] atIndex:0];
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
    [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; // Crashes here
}

#pragma mark - Table View

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return _objects.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; // Crashes here

    NSDate *object = _objects[indexPath.row];
    cell.textLabel.text = [object description];
    return cell;
}

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return NO if you do not want the specified item to be editable.
    return YES;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        [_objects removeObjectAtIndex:indexPath.row];
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    } else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
    }
}

/*
 // Override to support rearranging the table view.
 - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
 {
 }
 */

/*
 // Override to support conditional rearranging of the table view.
 - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
 {
 // Return NO if you do not want the item to be re-orderable.
 return YES;
 }
 */

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
        NSDate *object = _objects[indexPath.row];
        self.contactViewController.detailItem = object;
    }
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"showDetail"]) {
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        NSDate *object = _objects[indexPath.row];
        [[segue destinationViewController] setDetailItem:object];
    }
}

@end

它在CellRowAtIndexPath的第一行崩溃。由于我遇到麻烦,我也接受了How to insert items to a UITableView when a UIButton is clicked in iOS中的建议,但这并没有解决我的问题。

这令人非常沮丧,因为据我所知,我的代码(名称除外)与示例应用程序完全相同。

编辑:异常消息是

'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier Cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'

3 个答案:

答案 0 :(得分:2)

Alex - 在xCode中使用故事板和新的原型单元格功能时,必须在Interface Builder中设置一个标识符值,其值应与代码中的值相匹配。

所以请注意你有这一行:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

在这种情况下,您的小区标识符为“Cell”

您能否确认在Interface Builder / Storyboard中,您的表格视图单元格的标识符设置为相同?

举个例子,这是我正在构建的示例应用程序的屏幕截图(注意右边的我的标识符字段):

enter image description here

答案 1 :(得分:0)

我会推荐这个

-(void)ViewDidLoad{

    [tableView registerClass:[MyCell class] forCellReuseIdentifier:@"Cell"];
}

- (void)insertNewObject:(id)sender
{
    if (!_objects) {
        _objects = [[NSMutableArray alloc] init];
    }
    [_objects insertObject:[NSDate date] atIndex:0];
    [tableView reloadData]; //this will trigger cellForRowAtIndexPath again with the updated array
}

请你发错误。

答案 2 :(得分:0)

您不应该使用[self.tableView insertRowsAtIndexPaths: withRowAnimation:];。而不是这个,你应该调用[talbeView reloadData]方法。