背景
公司項(xiàng)目有一個(gè)消息的列表頁(yè)挎春,點(diǎn)擊自定義cell上的刪除按鈕執(zhí)行刪除操作
#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];
//錯(cuò)誤的寫法:
NSIndexPath* path =[NSIndexPath indexPathForRow:button inSection:0];
NSMutableArray* deleteArray=[NSMutableArray arrayWithObject:path];
[self.tableView deleteRowsAtIndexPaths:deleteArray withRowAnimation:UITableViewRowAnimationFade];
}
造成的后果
- 崩潰 :如果所有cell在屏幕的高度范圍內(nèi)可以全部展示出來(lái)祷杈,這時(shí)候刪除第一條數(shù)據(jù)斑司,再刪除最后一條數(shù)據(jù),會(huì)造成崩潰但汞,報(bào)錯(cuò)信息是數(shù)組越界
- 刪除數(shù)據(jù)不對(duì):如果刪除第一個(gè)數(shù)據(jù)后宿刮,接著刪除第二條數(shù)據(jù),會(huì)發(fā)現(xiàn)實(shí)際上是第三條數(shù)據(jù)被刪除了
原因分析
執(zhí)行deleteRowsAtIndexPaths只會(huì)重新執(zhí)行numberOfRowsInSection方法私蕾,而cellForRowAtIndexPath不會(huì)重新執(zhí)行僵缺,這使得每個(gè)cell的buttontag不變,不會(huì)根據(jù)刪除后的dataSource重新賦值踩叭。這時(shí)候數(shù)據(jù)源已經(jīng)減少磕潮,如果點(diǎn)擊最后一行的刪除按鈕翠胰,必然會(huì)引起數(shù)組越界。
如果列表較長(zhǎng)自脯,刪除數(shù)據(jù)時(shí)需要滑動(dòng)之景,這時(shí)候就不會(huì)出現(xiàn)上述的問題,因?yàn)榛瑒?dòng)會(huì)走cellForRowAtIndexPath方法膏潮,會(huì)使cell的buttontag屬性值及時(shí)得到更新锻狗。
解決辦法一
使用
- (void)deleteNewsBtnClicked:(NSInteger)button{
NSLog(@"----------正在刪除:%zd行",button);
[self.dataSource removeObjectAtIndex:button];
// 表格刷新
[self.tableView reloadData];
}
采用這種方法的缺點(diǎn)就是:
- 沒有自帶刪除動(dòng)畫
- reload會(huì)消耗更多資源
解決辦法二(推薦)
將cell通過代理傳出來(lái),再通過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];
}
這種方法的優(yōu)點(diǎn)就是沒有方法一的缺點(diǎn) 哈哈哈