deleteRowsAtIndexPaths 崩溃

2018-05-08  本文已影响0人  希达like
背景

公司项目有一个消息的列表页,点击自定义cell上的删除按钮执行删除操作

#import "MyCell.h"

、、、、、

-(void)rowDelete:(UIButton *)btn{
    if (self.delegate && [self.delegate respondsToSelector:@selector(deleteNewsBtnClicked:)]) {
        [self.delegate deleteNewsBtnClicked:self.buttonTag];
    }
}

#import "ViewController.h"

、、、、、、

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    MyCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
    if (!cell) {
        cell = [[MyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
        cell.delegate = self;
    }
    cell.titleLab.text = self.dataSource[indexPath.row];
    cell.buttonTag = indexPath.row;
    return cell;
}

、、、、、、

- (void)deleteBtnClicked:(NSInteger)button{
    NSLog(@"----------正在删除:%zd行",button);
    [self.dataSource removeObjectAtIndex:button];
    //错误的写法:
 NSIndexPath* path =[NSIndexPath indexPathForRow:button inSection:0];
    NSMutableArray* deleteArray=[NSMutableArray arrayWithObject:path];
    [self.tableView deleteRowsAtIndexPaths:deleteArray withRowAnimation:UITableViewRowAnimationFade];
}
造成的后果
原因分析

执行deleteRowsAtIndexPaths只会重新执行numberOfRowsInSection方法,而cellForRowAtIndexPath不会重新执行,这使得每个cell的buttontag不变,不会根据删除后的dataSource重新赋值。这时候数据源已经减少,如果点击最后一行的删除按钮,必然会引起数组越界。
如果列表较长,删除数据时需要滑动,这时候就不会出现上述的问题,因为滑动会走cellForRowAtIndexPath方法,会使cell的buttontag属性值及时得到更新。

解决办法一

使用

- (void)deleteNewsBtnClicked:(NSInteger)button{
    NSLog(@"----------正在删除:%zd行",button);
    [self.dataSource removeObjectAtIndex:button];
    // 表格刷新
    [self.tableView reloadData];
}

采用这种方法的缺点就是:

解决办法二(推荐)

将cell通过代理传出来,再通过cell找到其indexpath

#import <UIKit/UIKit.h>
@class MyCell;

@protocol LKLNewsDelegate <NSObject>
- (void)deleteNewsBtnClicked:(MyCell *)cell;
@end

@interface MyCell : UITableViewCell

@property (nonatomic, assign)id<LKLNewsDelegate>delegate;
@property(nonatomic,strong)UILabel *titleLab;

@end
#import "MyCell.h"
    、、、、、、
-(void)rowDelete:(UIButton *)btn{
    if (self.delegate && [self.delegate respondsToSelector:@selector(deleteNewsBtnClicked:)]) {
        [self.delegate deleteNewsBtnClicked:self];
    }
}
#import "ViewController.h"
       、、、、、
-(void)deleteNewsBtnClicked:(MyCell *)cell{
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    [self.dataSource removeObjectAtIndex:indexPath.row];
    [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];    
}

这种方法的优点就是没有方法一的缺点 哈哈哈

上一篇 下一篇

猜你喜欢

热点阅读