http://www.cnblogs.com/hellocby/archive/2012/05/23/2514469.html
UITableView通过重用单元格来达到节省内存的目的:通过为每个单元格指定一个重用标识符(reuseIdentifier),即指定了单元格的种类,以及当单元格滚出屏幕时,允许恢复单元格以便重用.对于不同种类的单元格使用不同的ID,对于简单的表格,一个标识符就够了.
假如一个TableView中有10个单元格,但是屏幕上最多能显示4个,那么实际上iPhone只是为其分配了4个单元格的内存,没有分配10个,当滚动单元格时,屏幕内显示的单元格重复使用这4个内存,以下代码用于测试内存的使用:
1 - (UITableViewCell *)tableView:(UITableView *)tableView
2 cellForRowAtIndexPath:(NSIndexPath *)indexPath
3 {
4 UITableViewCellStyle style = UITableViewCellStyleSubtitle;
5 static NSString *cellID = @"cell";
6 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
7 if (cell == nil)
8 {
9 cell = [[[UITableViewCell alloc] initWithStyle:style reuseIdentifier:@"cell"] autorelease];
10 cell.detailTextLabel.text = [NSString stringWithFormat:@"Cell %d",++count]; //当分配内存时标记
11 }
12 cell.textLabel.text = [NSString stringWithFormat:@"Cell %d",[indexPath row] + 1]; //当新显示一个Cell时标记
13 return cell;
14 }
通过运行此代码 会发现实际上分配的Cell个数为屏幕最大显示数, 当有新的Cell进入屏幕时,会随机调用已经滚出屏幕的Cell所占的内存,这就是Cell的重用
http://hi.baidu.com/306806106/item/e68d099a05e82e8b5814613b
通常在创建完UITableViewController后,会看到UITableViewDataSource的一个实现函数如下
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = [NSString stringWithFormat:@"Cell"];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
//config the cell
return cell;
}
而这些代码又是什么意思呢?
每一个UITableView里都维护着一个cell队列,当UITableView刚加载的时候,cell队列里是没有任何数据的。dequeueResableCellWithIdentifier从字面上理解就是”出列可重用的cell",也就是根据一个标识identifier从cell队列里取出一个UITableViewCell,当然了,如果cell队列里没有此标识的cell,调用此方法的结果就是返回nil。因此,在UITableView刚加载的时候,cell队列里没有可用的cell,所以必须通过语句
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
来创建对应CellIdentifier标识的UITableViewCell实例。
而当UITableView在滚动的时候导致UITableViewCell滚出手机屏幕视图的时候,程序会将这一个UITalbeViewCell实例放入此UITableView所维护的cell队列中。当UITableview中有新的UITableViewCell需要展现在手机屏幕视图上时,就会调用tableView:cellForRowAtIndexPath:方法了,因此我们可以知道以下几点:
1-重取出来的cell是有可能已经捆绑过数据或者加过子视图的,所以,如果有必要,要清除数据(比如textlabel的text)和remove掉add过的子视图(使用tag)。
2-这样设计的目的是为了避免频繁的 alloc和delloc cell对象而已,没有多复杂。
3-设计的关键是实现cell和数据的完全分离
如果不想重用UITableViewCell实例,如在一个每一行都显示不同内容的UITableView实例时,我们可以用如下的方法:
NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%d%d", [indexPath section], [indexPath row]];
来重新定义标识。
这样每一行都有其对应的identifier,从cell队列里取出来只有两个结果:
1-cell队列里没有此identifier对应的UITableViewCell实例,返回nil
2-cell队列里有此identifier对应的UITableViewCell实例,而且不会有重用到其他不同行的cell的情况
--------------------------------------------------------------------------------------------
将UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:改为
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
同事指点上一种办法不好,虽然改法简单,但是这浪费内存:
static NSString *CellIdentifier = @"CustomCellIdentifier";
// static BOOL nibsRegistered = NO;
if (!nibsRegistered) {
UINib *nib = [UINib nibWithNibName:@"CustomCell" bundle:nil];
[tableView registerNib:nib forCellReuseIdentifier:CellIdentifier];
nibsRegistered = YES;
}
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
定制tablecell要点:
1.首先 registerNib 注册 CellIdentifier
2.然后再用CellIdentifier进行实例化
通过文档,我自己研究了一下,用了两种方法解决了这个问题
1.每次都进委托方法的时候都,clear 一下 UITableViewCell ,代码是
if (cell!=nil) {
cell.textLabel.text=nil;
cell.detailTextLabel.text=nil;
cell.accessoryView=nil;
}
2.第二种方法是,用不同的字符串identifier来标记,不同的tableviewcell
//Construct UITableViewCell
NSString *FormViewSampleTableIdentifier;
UITableViewCell *cell;
static NSUInteger editablefalseCountFalse;
static NSUInteger editablefalseCountTrue;
if ([editable isEqualToString:@"false"]) {
FormViewSampleTableIdentifier=@"FormViewSampleTableIdentifierEditableFalse";
cell=[tableView dequeueReusableCellWithIdentifier:FormViewSampleTableIdentifier];
if (cell==nil) {
cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:FormViewSampleTableIdentifier];
if (textLabel!=nil) {
cell.textLabel.text=textLabel;
}
editablefalseCountFalse++;
NSLog(@"editablefalseCountFalse:%i",editablefalseCountFalse);
}
if (value!=nil)
{
cell.detailTextLabel.text=value;
}
}
else if([editable isEqualToString:@"true"])
{
FormViewSampleTableIdentifier=@"FormViewSampleTableIdentifierEditableTrue";
if (cell==nil) {
cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:FormViewSampleTableIdentifier];
if (textLabel!=nil) {
cell.textLabel.text=textLabel;
}
editablefalseCountTrue++;
NSLog(@"editablefalseCountTrue:%i",editablefalseCountTrue);
}
if (value!=nil)
{
UITextField *textField=[[UITextField alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 150.0f, 25.0f)];
textField.borderStyle=UITextBorderStyleRoundedRect;
textField.text=value;
textField.delegate=self;
cell.accessoryView=textField;
// NSLog(@"indexPath:%@",indexPath);
}
}
return cell;
上上下下拖动了很久之后,结果如下:2013-05-13 14:07:18.970 Rubic's Cube No StoryBoard[832:14003] editablefalseCountFalse:12013-05-13 14:07:18.974 Rubic's Cube No StoryBoard[832:14003] editablefalseCountFalse:22013-05-13 14:07:20.963 Rubic's Cube No StoryBoard[832:14003] editablefalseCountFalse:32013-05-13 14:07:22.115 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:12013-05-13 14:07:22.182 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:22013-05-13 14:07:25.928 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:32013-05-13 14:07:26.145 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:42013-05-13 14:07:54.060 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:52013-05-13 14:07:54.127 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:62013-05-13 14:08:40.041 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:72013-05-13 14:08:40.141 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:82013-05-13 14:08:40.778 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:92013-05-13 14:09:25.519 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:102013-05-13 14:09:25.762 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:11我分析,editablefalseCountFalse最大是3,说明也没常驻3个,这三个可以重用,但是editablefalseCountTrue就不能重用了,如果页面划到了会一直alloc增加。我把其中一个分支去掉,结果是:2013-05-13 14:35:34.000 Rubic's Cube No StoryBoard[937:14003] applicationDidBecomeActive:2013-05-13 14:35:35.414 Rubic's Cube No StoryBoard[937:14003] editablefalseCountFalse:12013-05-13 14:35:35.417 Rubic's Cube No StoryBoard[937:14003] editablefalseCountFalse:22013-05-13 14:35:36.719 Rubic's Cube No StoryBoard[937:14003] editablefalseCountFalse:3让我试试同事的方法,是怎么样的