操蛋的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滚 ...
随机推荐
- day6_python学习笔记_chapter8_条件,循环
1. if elif else 2. 条件表达式:三元操作符: smaller = x if x < y else y == if x < y : smaller =x else : ...
- jQ的自定义插件
此文运用的是优雅的Markdown而书 项目中写js时,有很多时候有需要重复利用的东西,我们可以给它们写成一个插件的形式,这样阅读性和适用性都会大大提高.最近抽个时间,好一番的研究了下 Jcrop 的 ...
- python 之日期时间处理
##python时间操作一般使用time.datetime两个模块 对于time模块,时间的表示模式有3种1.时间戳:time.time()2.字符串: time.strftime('%Y%m%d') ...
- 自增或自减例子:i++和++i的相同点和不同点
/* Name:++i和i++的区别 Copyright: By.不懂网络 Author: Yangbin Date:2014年2月15日 02:40:27 Description:熟悉前自增或自减的 ...
- opengl 正方体+模拟视角旋转
// first_3D.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <GL/glut.h> #includ ...
- 重拾javascript动态客户端网页脚本
笔记一: 一.DOM 作用: · DOM(Doument Object Model) 1.document文档 HTML 文件 (标记语言) <html> < ...
- MySQL、You are using safe update mode
MySQL默认模式是sql_safe_updates=1的.在这个模式下不管你是update还是delete一行where 条件都要指定主键.如果where条件只出现的不是主键就会出错. 例子: se ...
- QTabWiget Change Color 改变颜色(每个QWidget都有一个自己的调色板palette,设置它的颜色,然后setAutoFillBackground即可)
Qt中的QTabWiget 类提供了一个便签控件,但是这个控件默认初始化的颜色是白色,和原窗口的颜色不同,看起来非常的违和,所以我们希望将其的背景颜色设为当前窗口的背景颜色.我们所要做的就是先将应用程 ...
- Advanced Replication同步复制实验(基于Trigger&基于Materialized View)
1. 高级复制和流复制介绍 1.1 高级复制(Advanced Replication) 高级复制也称为对称复制,分为多主体站点复制(Multiple Master Rplication).物化视图站 ...
- HDU 4417 Super Mario
题解:函数式线段树求区间小于等于k的数有几个,离线做法,首先将所有询问和序列一起离散,然后用函数式线段树处理. #include <map> #include <cstdio> ...