底牌项目中的选择牌谱上传功能--深刻理解UITableView复用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010105969/article/details/52583210

最近底牌项目进行版本迭代,在原有的功能上加了一个发送编辑牌谱、发送牌谱的新功能。发送牌谱功能类似于发送图片功能,可选择牌谱时的功能却需要自己做。本人在做这块功能的时候遇到了一些问题,幸好最后解决了。下面一起说说这些问题,以及解决问题的方法。

可以先看一下效果图:

此界面的布局:

此界面由UITableView构成,根据日期的不同设置单元格,单元格内是一张张图片,在每张图片上添加了一个按钮用于选择图片。

问题:

在选中一张图片后会将该图片存储到一个数组中以便上传,可当再次点击按钮取消选中图片时却不知道该如何将该图片从数组中删除。

解决:

在Cell中制定协议设置代理,在选中图片的按钮点击事件中如果代理响应了协议中的方法则让代理执行该方法。关键:在该方法中要将图片的信息传递过去。代码:

if ([self.delegate respondsToSelector:@selector(tableViewCell:withImage:withPicId:withModel:)]) {

            [self.delegate tableViewCell:self withImage:picV.image withPicId:iD withModel:model];

        }else{

NSLog(@"CellInMyPokers的代理没有响应...");

        }

传递过去的图片是为了添加到图片上传数组中。   那么问题来了,如果现在已经选择了4张图片,而我此时不想选某张图片了该怎么办?解决办法:点击图片上的按钮同样执行协议中的方法,也就是上面贴出来的方法。将Cell的代理设置为当前的视图控制器,在控制器中执行代理方法,代码:

- (void)tableViewCell:(CellInMyPokers *)cell withImage:(UIImage *)image withPicId:(NSInteger)iD withModel:(ModelInPoker *)model{

if (self.selectedPokerArr.count == 0) {

        [self.selectedPokerArr addObject:image];

        [self.idArr addObject:model.iD];

    }else{

        [self.selectedPokerArr addObject:image];

        [self.idArr addObject:model.iD];

for (int i = 0; i < self.selectedPokerArr.count-1; i ++) {

NSString * id1 = self.idArr[i];

if ([model.iD isEqualToString:id1]) {

                [self.selectedPokerArr removeObjectAtIndex:i];

                [self.selectedPokerArr removeLastObject];

                [self.idArr removeObjectAtIndex:i];

                [self.idArr removeLastObject];

break;

            }

        }

    }

}

思路:将传递过来的图片和加入到数组中的图片进行比较,如果两张图片一样则将相同的图片移除,这样就达到了反选图片的效果。      可在实现过程中遇到了问题就是利用UIImage对象进行比较,发现不同的图片有时是相同的,现在还不知道是什么原因。于是放弃该方法,将图片的ID(图片的唯一标识)传递过来,然后比较两张图片的ID,如果相同就将图片从数组中移除。

解析代码:当存放图片的数组为空的时候,直接添加图片,同时将图片的ID放到另一个数组中。  当图片数组不为空时,如果有图片传递过来(不论是选择图片还是反选图片)就将其添加到图片数组中,同时将图片的ID添加到另一个数组中。然后对图片数组进行遍历,实际上是对图片数组中的图片ID进行遍历,如果最后添加的图片的ID和之前添加的图片ID相同就将ID相同的那张图片以及最后一张图片一起从数组中删除。

选择图片和反选图片的问题解决后又有了新的问题。

问题:

选中一张图片,然后滑动UITableView,这时发现之前选中的图片变成了没选中,如果是刷新和加载同样会出现这样的问题。

原因:UITableView复用的问题(UITableView复用就不在这里解释了)。

UITableView的复用可以节省内存空间,可如果不理解其本质地使用就会出现我所说的问题,有时还会出现同样的内容重复出现的问题(第一个单元格中的内容发生变化,后面的单元格复用第一个单元格,其上的内容也会和第一个单元格的内容相同)。

解决:

思路:每次使用单元格的时候将选中的图片和单元格中的图片进行比较,如果有相同的图片,则将相同图片上的按钮设置为选中状态。

之前已经将选中图片的image对象和图片的ID分别添加到了两个数组中,在设置单元格内容的方法中将选中图片ID(通过ID可以更好滴比较两个图片是否是同一张图片)传递过来。

代码:

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

CellInMyPokers * cell = [CellInMyPokers cellWithTableView:tableView withIndexPath:indexPath];

    cell.delegate = self;

    cell.model = self.dataSource[indexPath.row];

if (self.present.length > 0) {

        cell.present = @"present";

        cell.selectedPokerId = self.idArr;

    }

    cell.didRow = indexPath.row;

return cell;

}

cell.selectedPokerId = self.idArr;将选中图片的ID传递到了Cell中。在cell中做的处理代码:

- (void)setSelectedPokerId:(NSMutableArray *)selectedPokerId{

_selectedPokerId = selectedPokerId;

for (int i = 0; i < self.picVArr.count; i ++) {

ModelInPoker * model = [_model.rows objectAtIndex:i];

UIImageView * imageV = self.picVArr[i];

for (NSString * iD in _selectedPokerId) {

if ([iD isEqualToString:model.iD]) {

for (UIButton * btn in self.btnArr) {

if (btn.tag == imageV.tag) {

                        [btn setImage:[UIImage imageNamed:@"image_selected@3x"] forState:UIControlStateNormal];

                    }

                }

            }

        }

    }

}

这里需要我们深刻理解单元格的复用机制。

写的可能有些啰嗦,能帮助大家最好,不能的话就帮帮我之后的工作就好。

本文解决的两个关键问题:1.单元格的复用   2.图片的选中和反选

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏mukekeheart的iOS之旅

iOS学习——键盘弹出遮挡输入框问题解决方案

  在iOS或Android等移动端开发过程中,经常遇到很多需要我们输入信息的情况,例如登录时要输入账号密码、查询时要输入查询信息、注册或申请时需要填写一些信息...

56460
来自专栏谈补锅

通知 - NSNotificationCenter

1、每一个应用程序都有一个通知中心(NSNotificationCenter)实例,专门负责协助不同对象之间的消息通信;

12640
来自专栏xx_Cc的学习总结专栏

六天完成一个简单iOS App - 第三天

320110
来自专栏青青天空树

nodejs构建多房间简易聊天室

  本服务器需要提供两个功能:http服务和websocket服务,由于node的事件驱动机制,可将两种服务搭建在同一个端口下。

33010
来自专栏向治洪

react-native添加redux支持

redux简介 redux是一个用于管理js应用状态的容器。redux出现时间并不是很长,在它出现之前也有类似功能的模块出现,诸如flux等等。redux设计的...

31490
来自专栏从零开始学自动化测试

Selenium2+python自动化24-js处理富文本

前言 上一篇Selenium2+python自动化23-富文本(自动发帖)解决了富文本上iframe问题,其实没什么特别之处,主要是iframe的切换,...

30150
来自专栏iOS技术杂谈

NSNotificationCenter 通知的使用方法详解你要知道的KVC、KVO、Delegate、Notification都在这里

你要知道的KVC、KVO、Delegate、Notification都在这里 转载请注明出处 https://cloud.tencent.com/develop...

50860
来自专栏Scott_Mr 个人专栏

自定义转场详解(一)

35660
来自专栏大内老A

ASP.NET:创建Linked ValidationSummary, 深入理解ASP.NET的Validation

我想对于ASP.NET的Validator控件已经熟悉的不能再熟悉了。我们 已经习惯了用Validator控件来验证我们在表单的输入,并通过Validation...

32780
来自专栏Web 开发

给iOS的WebView添加远程调试

定位到 didFinishLaunchingWithOptions 代码块中。

9400

扫码关注云+社区

领取腾讯云代金券