UItableViewCell的复用机制,原理解答
今天在看iphone开发秘籍的时候,遇到这个问题,就仔细的深入了一下,通过测试,获取了一些自认为还不错的结论,希望对大家在cell复用方面遇到的一些问题会有所帮助。
本篇文章只讲原理,对于如果对cell做界面,不深入讲述。鉴于我的表达能力有限,可能会有我自己清楚,但是却说不清楚的地方,如有问题,留言给我。
UITableView在界面的编程用的甚多,iphone开发也三月有余了,每次用到cellForRowAtIndexPath的委托方法的时候,都是直接copy代码,自己略加一些界面的修改,对于cell的标示符都是static NSString* identifier = @"cell";然后调用dequeueReusableCellWithIdentifier方法获取cell,如果cell为空,再调用[[[UITableViewCellalloc]initWithStyle方法新创建一个,根本没有考虑过更深一些的东西。为了讲解清楚,现放上一段代码,代码copy自iphone开发秘籍,本人为了讲解,略加修改。以下所有讲解均依照此代码进行,因此,如果您希望能够透彻的了解cell的复用机制,建议实际运行以下,跟着讲解,查看效果。代码只有tableVIew的委托方法,因此您需要自己创建工程,把这些委托方法加进去。
上文一共四个委托方法,表明tableView一个section,有32行,高度为58.关于tableView的高度那个委托方法的返回的高度值,建议最好自己运行程序查看以下,最终达到一页的界面显示8个cell,第8个cell显示一半也行,但是不能显示9和7个cell。我这里之所以为58,由于(480 - 44)/ 58 为7.5 的样子,44为navigationBar的高度,480为屏幕的高度。总之,需要达到的效果是一页显示7个多的cell。还有那个icon.png需要自己准备了,要把它显示出来。是不是很麻烦呀?没办法,谁让我们在获得知识呢,知识总是需要点功夫的。
[cpp]
- (NSInteger)numberOfSectionsInTableView:(UITableView *)aTableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section
{
return 32;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 58;
}
- (UITableViewCell *)tableView:(UITableView *)tView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCellStyle style;
NSString *cellType;
switch (indexPath.row % 4)
{
case 0:
style = UITableViewCellStyleDefault;
cellType = @"Default Style";
//有标题没有正文(没有细节文字)。可选的图片
break;
case 1:
style = UITableViewCellStyleSubtitle;
cellType = @"Subtitle Style";
//标题和正文方式,上下排布。可选的图片
break;
case 2:
style = UITableViewCellStyleValue1;
cellType = @"Value1 Style";
//左边文字左对齐,右边文字右对齐。可选的图片
break;
case 3:
style = UITableViewCellStyleValue2;
cellType = @"Value2 Style";
//左边文字右对齐,蓝色;右边文字左对齐,黑色。没有图片
break;
}
static int i = 0;
UITableViewCell *cell = [tView dequeueReusableCellWithIdentifier:cellType];
if (!cell)
{
cell = [[[UITableViewCell alloc] initWithStyle:style reuseIdentifier:cellType] autorelease];
++i;
NSLog(@"cell created %d times", i);
}
if (indexPath.row > 3)
cell.imageView.image = [UIImage imageNamed:@"icon.png"];
cell.textLabel.text = cellType;
cell.detailTextLabel.text = @"Subtitle text";
return cell;
}
首先讲解一下复用队列:
复用队列的元素增加:只有在cell被滑动出界面的时候,此cell才会被加入到复用队列中。每次在创建cell的时候,程序会首先通过调用dequeueReusableCellWithIdentifier:cellType方法,到复用队列中去寻找标示符为“cellType”的cell,如果找不到,返回nil,然后程序去通过调用[[[UITableViewCell alloc] initWithStyle:style reuseIdentifier:cellType] autorelease]来创建标示符为“cellType”的cell。
先运行一次程序,不要滑动cell,查看打印日志,会有打印"cell create 1 times",,,"cell create 8 times",一共有8个日志,表明cell创建了8次,这个日志打印是在cellForRowAtIndexPath中的创建cell的时候打印的。然后慢慢向下(向下的意思,实际上是手向上滑动,让界面显示下一个cell,向上与之相反)滑动cell,到显示第九个cell的时候,会看到打印一条日志"cell create 9 times",然后继续慢慢向下滑动,会有"cell create 10 times",直到滑动到第12个cell以后,cell被创建了12个之后,以后再怎么滑动,cell都不会被创建了。也就是说本tableView要完整的工作,一共创建了12个cell。
开始解释原因了:
第一页的界面一共需要展示8个cell,故而cell需要创建8次,每一个cell负责自己的数据显示。此8个创建以后,复用队列依然为空(因为你此时还没有滑动cell呢,复用队列的元素不会增加)。然后在向下滑动显示出第9个cell的时候,还会调用cellForRowAtIndexPath方法,在此方法中,它首先到可复用队列中去找,由于此时队列为空,它创建了一个cell,打印日志,同时当第1个cell滑动出界面之外,第一个cell进入到复用队列中,队列中有一个元素,此元素的表示符为@"Default Style"。然后继续向下滑动cell,开始显示第10个cell,它同样到复用队列中去找,第10个cell的标示符为@"Subtitle Style",但是队列中唯一的cell的标示符为@"Default Style",根据标示符寻找,没有找到,故而再次创建一个新的cell,同时将滑动出界面的第2个cell进入复用队列。此时复用队列有两个元素,标示符为@"Default Style",@"Subtitle Style"。同样的道理,滑动到第11个cell的时候,第3个cell入队,第12个cell的时候,第4个cell入队。此时复用队列的元素个数为四个,标示符分别为:@"Default Style",@"Subtitle Style",@"Value1 Style",@"Value2 Style".然后继续滑动cell,当滑动到第13个cell的时候,它的标示符为@"Default Style",它到复用队列中去找,可以找到。故而,这个cell就不会被创建了,同理,再次向下滑动,以下的所有cell都可以根据标示符找到对应的cell,不会有被创建的。在向下滑动的过程中,滑动出去的cell会被入队,不过只入队创建了的cell,也就是说最终队列中会有12个cell。
补充:软件开发 , C++ ,