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

来源:互联网 发布:js 每隔一加一 编辑:程序博客网 时间:2024/04/29 07:27

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

可以先看一下效果图:

此界面的布局:

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

问题:

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

解决:

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

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

            [self.delegatetableViewCell:selfwithImage:picV.imagewithPicId: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.selectedPokerArraddObject:image];

        [self.idArraddObject:model.iD];

    }else{

        

        [self.selectedPokerArraddObject:image];

        [self.idArraddObject:model.iD];

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

            

            NSString * id1 =self.idArr[i];

            if ([model.iDisEqualToString:id1]) {

                [self.selectedPokerArrremoveObjectAtIndex:i];

                [self.selectedPokerArrremoveLastObject];

                

                [self.idArrremoveObjectAtIndex:i];

                [self.idArrremoveLastObject];

                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 = [CellInMyPokerscellWithTableView:tableViewwithIndexPath: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.rowsobjectAtIndex:i];

        UIImageView * imageV =self.picVArr[i];

        

        for (NSString * iDin _selectedPokerId) {

            if ([iDisEqualToString:model.iD]) {

                for (UIButton * btnin self.btnArr) {

                    

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

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

                    }

                }

                

            }

        }

        

    }

}

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

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

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


1 0
原创粉丝点击