iOS / Objective-C:删除行后应用程序崩溃

时间:2017-02-18 00:48:56

标签: ios objective-c uitableview

当我尝试从此UItable中删除对象/行时,apllication与日志崩溃:

  

NSInternalInconsistencyException',原因:'无效更新:无效   第0节中的行数。

编辑:

代码中有变化,现在插入新对象,删除的对象实际上已被删除,但只有在崩溃和重新启动后...所以,删除仍然失败,同一个日志,无效的uptade ...新代码:

    @interface TableViewController ()

@property NSMutableArray *users;
@property NSArray *detailList;
@property (strong) NSMutableArray *locations;


@end

@implementation TableViewController

- (IBAction)delete:(UIBarButtonItem *)sender {
    self.tableView.editing = !self.tableView.editing;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    self.tableView.dataSource = self;

    self.detailList=@[@"Your Favourite Spots",@"Our suggestion"];

}

-(void)viewDidAppear:(BOOL)animated{
    _locations = [[Spot spotType:@"users"]mutableCopy];
    _users=[[Spot spotWithType:@"users"]mutableCopy];

    [self.tableView reloadData];

}


#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return 2;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    return [self.detailList objectAtIndex:section];

}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    NSArray *places=[self containerWithSection:section];

    return places.count; 
}


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

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

    NSArray *places=[self containerWithSection:indexPath.section];
    Spot *spot = [places objectAtIndex:indexPath.row];

    [cell.textLabel setText:[NSString stringWithFormat:@"%@", spot.name]];

    return cell;
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    if ([segue.identifier isEqualToString:@"detail"]) {
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];

        NSArray *places = [self containerWithSection:indexPath.section];

        DetailViewController * destination = segue.destinationViewController;

        destination.spot =  [places objectAtIndex:indexPath.row];


    }
}


- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    if (editingStyle == UITableViewCellEditingStyleDelete) {

        NSPersistentContainer *persistenceContainer = [AppDelegate sharedDelegate].persistentContainer;

        NSManagedObjectContext *context = persistenceContainer.viewContext;

        NSMutableArray *places = [self containerWithSection:indexPath.section];

        Spot *spot = [places objectAtIndex:indexPath.row];

        [context deleteObject: spot];

        NSError *error;

        [context save:&error];

        if (!error) {
            NSLog(@"%@", error);
        }

        [places removeObject:spot];


        [self updateItemInSection:indexPath.section];


        [tableView deleteRowsAtIndexPaths:@[indexPath]withRowAnimation:UITableViewRowAnimationFade];
    }

    [tableView reloadData];

}

#pragma mark - Aux methods

- (void)updateItemInSection:(NSUInteger)section{

    switch (section) {
        case 0:{
            _locations = [[Spot allSpots]mutableCopy];
        }
            break;

        case 1:{
            _users = [[Spot spotType:@"users"]mutableCopy];
        }
            break;    
    }
}


#pragma mark - Aux methods

- (NSMutableArray*)containerWithSection:(NSUInteger)section {

    NSMutableArray *thisContainer;

    switch (section) {

        case 0:
            thisContainer = self.locations;
            break;

        case 1:
            thisContainer = self.users;
            break;   
    }
    return thisContainer;  
}

@end

2 个答案:

答案 0 :(得分:1)

删除/插入数据对象后,需要首先更新数据数组,然后再要求表重新加载数据。这就是崩溃的原因以及表格没有使用新元素进行更新。
如果你考虑到这个推理,我们会有一个良好的学习曲线吗?尝试一次在代码中进行必要的更改。
请记住,在任何更改,插入,删除数据=>首先,更新您的数据数组=>然后,[table reloadData]

因此,现在要处理删除单元格,我们将添加一个函数updateItemInSection:,负责执行表格数据更新&将从tableView:commitEditingStyle:forRowAtIndexPath:调用

这就是它的样子:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    if (editingStyle == UITableViewCellEditingStyleDelete) {

        NSPersistentContainer *persistenceContainer = [AppDelegate sharedDelegate].persistentContainer;

        NSManagedObjectContext *context = persistenceContainer.viewContext;

        NSManagedObject *spot = [_lisbonSpots objectAtIndex:indexPath.section];

        [context deleteObject: spot];

        NSError *error;

        [context save:&error];

        if (!error) {
           NSLog(@"%@", error);        
        }

        [_lisbonSpots removeObject:spot];

        // new function invocation here
        [self updateItemInSection:indexPath.section]; 

        [tableView deleteRowsAtIndexPaths:@[indexPath]withRowAnimation:UITableViewRowAnimationFade];
    }
}

- (void)updateItemInSection:(NSUInteger)section{

    switch (section) {
        case 0:{
            _bar = [Spot spotType:@"bar"];
        }
            break;

        case 1:{
            _restaurant = [Spot spotType:@"restaurant"];
        }
            break;

        case 2:{
            _club = [Spot spotType:@"club"];
        }
            break;

        case 3:{
            _others = [Spot spotType:@"others"];
        }
            break;
    }
}

- (NSArray*)containerWithSection:(NSUInteger)section {

    NSArray *thisContainer;

    switch (section) {

        case 0:
            thisContainer = self.bar;
            break;

        case 1:
            thisContainer = self.restaurant;
            break;

        case 2:
            thisContainer = self.club;
            break;

        case 3:
            thisContainer = self.others;
            break;
    }

    return thisContainer;
}

答案 1 :(得分:0)

问题是名称令人困惑......使用编辑过的代码,解决方案就是:

processing.threading

但如果没有@ystack

的帮助,我就无法实现