iOS 不要使用tag传递TableViewCell的indexPath值
2015-09-15 16:17
471 查看
http://itony.me/258.html
今天改一个UIcollectionView 的一个功能,点击cell里的按钮删除这个cell,然而对cell里的button添加addTarget属性并不能传递indexPath参数
于是找了好久才找到这篇文章。
我的代码在cell.button.tag = indexPath.row;
cell.button addTartget:self action:@selector(onClick:) forControlEvents:UIControlEventTouchUpInside
- (void)onClick:(UIButton *)sender{
UICollectionViewCell *cell = (UICollectionViewCell *)sender.superview.superview;
NSIndexPath *indexPath = [我的Collectionview
indexPathForCell:cell];
}
下面是原来文章的原文
之前我在项目中总是会遇到这样的情况:在UITableViewCell中添加了一个UIButton,UIButton点击后触发buttonPress:方法,在方法被调用后需要知道用户点击的是哪一个Cell。
原来我的做法是button.tag = indexPath.section 或者 button.tag = indexPath.row,很简单 =。= 隐约总觉得这种实现方式不是正规做法,但一直也没想起来改。
错误代码示范,请勿模仿:
今天我发现了这样做的弊端。我在TableView中需要实现一个删除操作:点击Cell中的删除按钮后,删除当前行的Cell,使用动画效果。我是这样实现的:
ok,我删除掉啦,看上去一切良好~
然后程序点击两下就崩掉了。。。
看了下抛出的异常,说代码中访问了不存在的indexPath.section或row值。想了想明白了:原来都是使用UIButton的tag进行记录indexPath值的,但是这种删除操作执行后,UIButton的tag值是不会更新的,只有在执行[_tableView reloadData]方法(或滑动列表,这时会调用cellForRowAtIndexPath方法)才能刷新。
所以这时TableViewCell中的button.tag值已经不对了!这时对Cell做操作,获得的indexPath值根本不对,程序报错是必然的。
当然是使用正规的办法获取indexPath值!如何做呢?
使用tag值传递indexPath是一种不安全的做法。因为它和原始值之间没有“强联系”。这就像人传话,a直接与b交流没什么问题,但a委托j再委托k再委托l传话给b时,就很难保证不出问题。在上述例子中,就是由于tableView列表中的cell发生变化,而tag存储的值是“二手数据”,因而给后面的代码传值出错,导致最终程序崩溃。所以在程序设计时,要尽量避免使用这种“二手数据”,一来保证数据正确,二来减少代码维护量。
之前的错误方法用了好久,到今天才发现……实在是有些惭愧啊。
今天改一个UIcollectionView 的一个功能,点击cell里的按钮删除这个cell,然而对cell里的button添加addTarget属性并不能传递indexPath参数
于是找了好久才找到这篇文章。
我的代码在cell.button.tag = indexPath.row;
cell.button addTartget:self action:@selector(onClick:) forControlEvents:UIControlEventTouchUpInside
- (void)onClick:(UIButton *)sender{
UICollectionViewCell *cell = (UICollectionViewCell *)sender.superview.superview;
NSIndexPath *indexPath = [我的Collectionview
indexPathForCell:cell];
}
下面是原来文章的原文
之前我在项目中总是会遇到这样的情况:在UITableViewCell中添加了一个UIButton,UIButton点击后触发buttonPress:方法,在方法被调用后需要知道用户点击的是哪一个Cell。
原来我的做法是button.tag = indexPath.section 或者 button.tag = indexPath.row,很简单 =。= 隐约总觉得这种实现方式不是正规做法,但一直也没想起来改。
错误代码示范,请勿模仿:
123456789101112131415161718192021 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *CellIdentifier = @"testCell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; UIButton *avatarBtn = [UIButton buttonWithType:UIButtonTypeCustom]; [avatarBtn addTarget:self action:@selector(avatarButtonPress:) forControlEvents:UIControlEventTouchUpInside]; [cell.contentView addSubview:avatarBtn]; } avatarBtn.tag = indexPath.row; //用button的tag属性传递当前cell的row值 //....} - (void)avatarButtonPress:(UIButton*)sender{ int row = sender.tag; //获得之前设置的row值 //....} |
1 2 3 4 5 6 7 8 9 | - (void)deleteButtonPress:(UIButton*)sender { int section = sender.tag; //使用tag传递Cell的indexPath.section值 [_tableView beginUpdates]; [_tableView deleteSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationLeft]; [_tableView endUpdates]; } |
然后程序点击两下就崩掉了。。。
看了下抛出的异常,说代码中访问了不存在的indexPath.section或row值。想了想明白了:原来都是使用UIButton的tag进行记录indexPath值的,但是这种删除操作执行后,UIButton的tag值是不会更新的,只有在执行[_tableView reloadData]方法(或滑动列表,这时会调用cellForRowAtIndexPath方法)才能刷新。
所以这时TableViewCell中的button.tag值已经不对了!这时对Cell做操作,获得的indexPath值根本不对,程序报错是必然的。
解决办法是?
当然是使用正规的办法获取indexPath值!如何做呢?1 2 3 4 5 6 7 8 | - (void)deleteButtonPress:(UIButton*)sender { //首先获得Cell:button的父视图是contentView,再上一层才是UITableViewCell UITableViewCell *cell = (UITableViewCell *)sender.superview.superview; //然后使用indexPathForCell方法,就得到indexPath了~ NSIndexPath *indexPath = [_tableView indexPathForCell:cell]; } |
一点思考
使用tag值传递indexPath是一种不安全的做法。因为它和原始值之间没有“强联系”。这就像人传话,a直接与b交流没什么问题,但a委托j再委托k再委托l传话给b时,就很难保证不出问题。在上述例子中,就是由于tableView列表中的cell发生变化,而tag存储的值是“二手数据”,因而给后面的代码传值出错,导致最终程序崩溃。所以在程序设计时,要尽量避免使用这种“二手数据”,一来保证数据正确,二来减少代码维护量。之前的错误方法用了好久,到今天才发现……实在是有些惭愧啊。
相关文章推荐
- ios 定位 航向检测
- SVProgressHUD–比MBProgressHUD更好用的 iOS进度提示组件
- SVProgressHUD–比MBProgressHUD更好用的 iOS进度提示组件
- iOS 定位精度
- ios socket第三方框架 AsyncSocket使用简介,连接,心跳,断线,数据发送与接收
- iOS学习资源搜集
- IOS开发+(void)load与+(void)initialize区别
- Crashlytics——iOS crash log 解析利器
- ios 线程安全单例写法
- 【投稿】iOS蓝牙开发(一)蓝牙相关基础知识
- iOS runtime方法详解之添加类
- IOS贝塞尔曲线圆形进度条和加载动画
- ios 关于scrollview内空间位置与想象不符的解决办法
- iOS设置分割线从边框顶端开始
- ios 读取图片
- VMware虚拟机 停电 无法启动
- iOS开发的一些奇巧淫技
- iOS地图适配
- iOS数据持久化(三)
- ios 将时间戳转换成标准时间