操蛋的UITableView重用机制
1,背景
你可能会遇见一下情况:
使用UITableView加载数据,比如你的每一个cell上面有一个UITextField,当你在第一个cell的UITextField中写下了内容,开始下滑UITableView,你会发现由于UITableView重用机制的影响,你的第一个UITextField的值会发生变化,令人费解啊,抓狂!
之类的情况可能很多,下面咱们就总结一下发生这种情况的原因,针对这种原因,咱们找到对应的解决办法。
2,用自己的话说UITableView的重用机制
当遇见这中情况的时候,我问过好多个ios程序员,他们多数的解决办法是直接不让它重用了,当然了,这样的话,表面上确实解决了问题,但是却给自己的程序带来了很大的隐患。我们做东西,应该去想着做最好的东西出来,不能这样草草的应付。
好了,言归正传。
所谓重用机制,就是模板共用一套,换的是内容。比如;view上显示七个cell,当第一个cell消失,第八个cell出现,那么第八个cell用的还是第一个cell,只不过他把第一个cell的内用换成了自己的。这就是重用的原理。问题就出现在他在换内容的时候,没换好,就出现了错误。
那么为什么会出现这种错误呢,为什么我们替换内容的时候根本就没有错,重用后还会出现错误呢?
不说废话 直接说我遇见的问题以及我的解决办法:
我的问题是右边的UITableView在上下滑动的时候按钮出现了重用,点过之后的按钮会发生变化,分成两个按钮,一个加菜按钮一个减菜按钮
当我点了第一个cell后,分裂成功,我将UITableView向下滑,却出现了第一个cell的按钮又变回了原型。
出现的原因:这个cell是我自定义的,这个按钮的状态是没有记录的,一次重用后他会和原来的状态一样。
解决办法:我是这样想的解决办法,之所以个重用是因为第一个和第八个没有特别的标注,我必须想一个区分第一个和第八个的属性,那么就有了indexpath.row,一位他们即使在重用这个值也不会相同,因此我们就用这个属性解决这个操蛋的问题。
好了,原理是这样,来看看我的解决代码吧;
[self.dataArr enumerateObjectsUsingBlock:^(NSDictionary * obj, NSUInteger idx, BOOL *stop) {
[self.tempDotNumberDic setValue:[obj valueForKey:@"number"] forKey:[obj valueForKey:@"ProID"]];
}];
说明:dataArr是tableview的数据源,tempDotNumberDic是一个记录点菜份数的字典,他的key是点菜id(因为id是唯一的,这样可以区分开),他的value是点菜份数。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView.tag == 100)
{
static NSString * strMark = @"cellMark";
DishesClassCell * cell = [tableView dequeueReusableCellWithIdentifier:strMark];
if (cell == nil)
{
cell = [[DishesClassCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:strMark];
}
if (indexPath.row<self.myClassArr.count)
{
cell.textContentLab.text = [[self.myClassArr objectAtIndex:indexPath.row] valueForKey:@"ClassName"];
}
if (self.tempClassDic.count>0)
{
NSString * result = [self.tempClassDic valueForKey:[NSString stringWithFormat:@"%d",indexPath.row]];
if ([result isEqualToString:@"1"])
{
cell.backgroundImageView.image = [UIImage imageNamed:@"DishClass06.png"];
}
else
{
cell.backgroundImageView.image = [UIImage imageNamed:@"DishClass05.png"];
}
}
return cell;
} NSString *str1 = [NSString stringWithFormat:@"cellmark%d",selectRow];
NSString * strMark1 = str1; //不停类别用不同的重用标示符,目的是为了不同分类同一位置的重用现象。
DishesDetailListCell * cell1 = [tableView dequeueReusableCellWithIdentifier:strMark1];
__block int dotNumber = 0;
if (indexPath.row < self.myProArr.count)
{
__block NSString * proID;
NSString * currID = [[self.myProArr objectAtIndex:indexPath.row] valueForKey:@"ProID"];
[self.dataArr enumerateObjectsUsingBlock:^(NSDictionary * obj, NSUInteger idx, BOOL *stop) {
proID = [obj valueForKey:@"ProID"];
if ([currID isEqualToString:proID])
{
dotNumber = [[[[DataBase selectNumberFromProId:[currID intValue]] objectAtIndex:0] valueForKey:@"number"] intValue];
}
}];
} if (cell1 == nil)
{
cell1 = [[DishesDetailListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:strMark1 andDotNumber:dotNumber];
}
cell1.dishView.myLab.text = [NSString stringWithFormat:@"点%d份",dotNumber];
int resylt = [[self.tempDotNumberDic valueForKey:[[self.myProArr objectAtIndex:indexPath.row] valueForKey:@"ProID"]] intValue];
if (resylt == 0)
{
[cell1.dishView zeroState];
}
else
{
[cell1.dishView initView:resylt];
}
if (indexPath.row%2 == 0)
{
cell1.backgroundImageView.image = [UIImage imageNamed:@"5.png"];
}
else
{
cell1.backgroundImageView.image = [UIImage imageNamed:@"6.png"];
}
cell1.selectionStyle=UITableViewCellSelectionStyleNone;
cell1.selectedBackgroundView = [[UIView alloc] initWithFrame:cell1.frame];
cell1.titleLab.text = [[self.myProArr objectAtIndex:indexPath.row] valueForKey:@"ProName"];
NSString * str = @"¥";
NSString * priceStr = [[self.myProArr objectAtIndex:indexPath.row] valueForKey:@"prices"];
cell1.priceLab.text = [str stringByAppendingFormat:@"%@",priceStr];
cell1.dishView.price = [priceStr doubleValue];
cell1.dishView.index = indexPath.row; [cell1.dishView.rightButton addTarget:self action:@selector(rightButtonClickEvent:) forControlEvents:UIControlEventTouchUpInside];
[cell1.dishView.leftButton addTarget:self action:@selector(leftButtonClickEvent:) forControlEvents:UIControlEventTouchUpInside];
[cell1.dishView.bigButton addTarget:self action:@selector(bigButtonClickEvent:) forControlEvents:UIControlEventTouchUpInside]; NSString * pathURL = ALL_URL;
NSURL * url = [NSURL URLWithString:[pathURL stringByAppendingFormat:@"%@",[[self.myProArr objectAtIndex:indexPath.row] valueForKey:@"ProductImg"]]];
[cell1.leftImageView setImageWithURL:url placeholderImage:[UIImage imageNamed:ALL_NO_IMAGE]];
return cell1;
}
看红色部分的代码,这点就是避免问题出现的办法,因为这个值是不同的cell值不同。
感觉自己的想法没有表达清楚,有什么问题直接留言。
操蛋的UITableView重用机制的更多相关文章
- UI之UItableView重用机制的性能问题
*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...
- IOS开发—UITableView重用机制的了解
引言 对于一个UITableView而言,可能需要显示成百上千个Cell,如果每个cell都单独创建的话,会消耗很大的内存.为了避免这种情况,重用机制就诞生了. 假设某个UITableView有100 ...
- iOS - UITableView中Cell重用机制导致Cell内容出错的解决办法
"UITableView" iOS开发中重量级的控件之一;在日常开发中我们大多数会选择自定Cell来满足自己开发中的需求, 但是有些时候Cell也是可以不自定义的(比如某一个简单的 ...
- iOS基础篇(十三)——UITableView(一)重用机制
UITableView是app开发中常用到的控件,功能很强大,常用于数据的显示.在学习UITableView使用之前,我们先简单了解一下: 1.UITableView的重用机制 UITableView ...
- UITableView动态存放、重用机制
一.UITableView动态存放 #import "ViewController.h"@interface ViewController ()<UITableViewDel ...
- 解决UITableView中Cell重用机制导致内容出错的方法总结
UITableView继承自UIScrollview,是苹果为我们封装好的一个基于scroll的控件.上面主要是一个个的 UITableViewCell,可以让UITableViewCell响应一些点 ...
- iOS学习笔记(4)— UITableView的重用机制
UITableView中的cell是动态的,在使用过程中,系统会根据屏幕的高度(480)和每个cell的高度计算屏幕中需要显示的cell的个数.比如,cell高度为90.那么480 / 90 = 5 ...
- ios UITableView中Cell重用机制导致内容重复解决方法
UITableView继承自UIScrollview,是苹果为我们封装好的一个基于scroll的控件.上面主要是一个个的 UITableViewCell,可以让UITableViewCell响应一些点 ...
- iOS之UITableView中的cell因为重用机制导致新的cell的数据出现重复或者错乱
UITableView中的cell可以有很多,一般会通过重用cell来达到节省内存的目的:通过为每个cell指定一个重用标识符(reuseIdentifier),即指定了单元格的种类,当cell滚 ...
随机推荐
- 如何让对象只在堆或者栈中分配空间ANDC++禁止一个类被继承
在开始之前先来分析一下C++中的new运算符和operator new之间的关联. new:指我们在C++里通常用到的运算符,比如A* a = new A或者调用带参数的构造函数; 对于new来说, ...
- Django Web开发【1】Django简介
前言 看完<Django Book>之后, 总想找个实例来实战开发下,无奈国内Django的书籍相当少,只能从英文书籍中吸取养料,偶然之后得到Learning Website Develo ...
- QR Code於台灣各行業的行銷應用案例介紹
當走在東京的大街小巷時,在五花八門的廣告看板.雜誌.護照簽證.海關.宣傳品.廣告.旅遊和導覽手冊.產品包裝.甚至在餐廳菜單上,皆可看到上面有一組黑色神秘二維條碼圖案:QR Code,當看到有興趣的商品 ...
- 将 SQL Server 实例设置为自动启动(SQL Server 配置管理器)
本主题说明如何使用 SQL Server 配置管理器在 SQL Server 2012 中将 SQL Server 实例设置为自动启动. 在安装过程中,SQL Server 通常配置为自动启动. 如果 ...
- Module中引用Module中的Activity时报错了,错误是找不到R文件中的id引用
1.好像库modul和主modul不能有相同名字和layout文件 2.资源文件名冲突导致的
- [VC6 console]调用API获取手机归属地
为了完成作业,就偷个懒糊了个获取手机归属地的程序,.我原本写的是MFC版本的,但是由于MFC的代码不是很通用,加上我没有学MFC的时候看别人MFC代码只能干瞪眼,看不懂,所以便改成控制台版本的了.但这 ...
- Linux操作系统定时任务系统Cron入门、PHP计划任务以及rpc示例
一.简单介绍 1.cron是一个linux下的定时执行工具,可以在无需人工干预的情况下运行作业.由于Cron 是Linux的内置服务,但它不自动起来,可以用以下的方法启动.关闭这个服务: servic ...
- hibernate-search-5.1.1简易使用
系统要求java7和hibernate-core-4.3.8,此外还依赖如下jar包 使用demo如下: package com.ciaos.controller; import java.io.IO ...
- hdu 2421 Deciphering Password(约数个数问题)
http://acm.hdu.edu.cn/showproblem.php?pid=2421 A^B 能够写成 p1^e1 * p2^e2 * .....*pk^ek.(A.B <= 10000 ...
- 整数数组的定义,然后输入一个整数X,假定X不在这个数组,返回小于X位置的最大数目i而超过X位置的最小数目j
//整数数组的定义,然后输入一个整数x,假定X不在这个数组,返回小于X位置的最大数目i而超过X位置的最小数目j: //如果X在该阵列,返回位置的阵列中的数. 资源: #include<iostr ...