ios基础之UITableViewCell的重用(带示例原创)

摘要:
我们创建了一个新的单视图项目,在故事板上拖动了一个表视图,用最基本的方法绑定了单元格,并使用了重用。因为当前窗口中显示了11个单元格,尽管最后一个窗口中只显示了其中的一半。

之前一个月刚刚系统的开始接触IOS开发,对UI控件大体了解了一遍,但是因为没有实际的参与项目,对细枝末节的还是不很清楚。

昨天突然想到:UITableViewCell的重用到底是怎么回事,上网查了许多资料后略有体会,但大都差不多,于是想自己实验一下。

便新建了个single view的工程,在storyboard上拖了个tableview,用最基础的方法绑定了cell,并用了重用。

 1 -(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 2 {
 3     //为表格行定义一个静态字符串作为标示
 4     static NSString *cellID = @"cellId";
 5     NSLog(@"hanghao:%ld",(long)indexPath.row);
 6     //从可重用的表格行的队列中取出一个表格行
 7     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
 8     if (cell == nil) {
 9         NSLog(@"重新创建对象");
10         switch (indexPath.row % 4) {
11             case 0:
12                 //使用UITableViewCell创建普通单元格,使用自定义的LYCTableViewCell创建自定义单元格
13                 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID];
14                 break;
15             case 1:
16                 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
17                 break;
18             case 2:
19                 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellID];
20                 break;
21             case 3:
22                 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:cellID];
23                 break;
24             default:
25                 break;
26         }
27     }
28     //单元格设为圆角
29     cell.layer.cornerRadius = 12;
30     cell.layer.masksToBounds = YES;
31     
32     //获取当前的行号
33     NSUInteger rowNo = indexPath.row;
34     cell.textLabel.text = [books objectAtIndex:rowNo];
35     //为uitableviewcell左端设置图片
36     cell.imageView.image = [UIImage imageNamed:@"123.png"];
37     //设置左端高亮图片
38     cell.imageView.highlightedImage = [UIImage imageNamed:@"123_h.png"];
39     
40     cell.detailTextLabel.text = [details objectAtIndex:rowNo];
41     return cell;
42 }

说实话,刚开始接触的时候真不知道 dequeueReusableCellWithIdentifier  这是个什么东西,后来在网上搜索的时候说这是根据id查找可重用的cell,但是说的太笼统了,到底什么算是可重用cell?

如果这个table中有多个自定义类型的cell,该怎么重用,这个问题纠结了一下午,到晚上睡觉前终于想通了。

先说简单的情况,当我们的tableview种的cell为单一类型,而且cell的高度是一个统一的高度,即显示一个这样的列表:

ios基础之UITableViewCell的重用(带示例原创)第1张

例如上图,那么在 -(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

方法中,if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cID];
    }

这几行代码将被执行11次,也就是创建11个指向不同地址的cell。

为什么是11次?因为当前window中显示了11个cell,虽然最后一个只显示了一半。(如果在iphone 6 plus中,创建的cell肯定大于11个,因为屏幕比5s的大)

这是在静止时候创建的cell。

那么当我们滑动屏幕的时候,有会发生或者触发哪些操作呢?

ios基础之UITableViewCell的重用(带示例原创)第2张

上面的图中,为将tableview向上滑动了一点,出现了一个新的cell(android高级),这个时候,系统会在创建一个新的cell对象,此时的内存中会有12个cell的对象。

当我们继续向上滑动,当[C#高级编程]对应的那个cell消失在tableview的可视区域的时候,那个cell将被tableview放到他的重用列表中。

而新出现的cell将会重用重用列表中的那个cell,只是对cell中的文本重新赋值而已,

这样一直循环:当用户滚动tableview时,如果cell不可见,将被扔进可重用列表,在其他行即将显示在tableview中时,重用那个cell,重新复制,以达到节省内存的效果。

按照上面的例子,那么内存中最多会创建12个cell,即使你的datasource中有1000条数据,也还是12个cell对象在内存中,只是tableview替我们控制了显示隐藏时重用cell。

如果我们不在编程时使用重用机制,那么可想而知,创建1000个甚至10000个cell在内存中,是多么浪费。

上面讲了单一种类cell的现实,那么多种cell是怎么显示的呢,其实只要上面的思路清晰了,那么多种cell也是同样的道理。

先上一下源代码

 1 #pragma mark - Table view data source
 2 
 3 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
 4     // Return the number of sections.
 5     return 4;
 6 }
 7 
 8 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
 9     // Return the number of rows in the section.
10     NSLog(@"rowNumber");
11     if (section % 2 == 0) {
12         return 1;
13     }
14     return 30;
15 }
16 
17 
18 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
19     static NSString *defaultCellID = @"default";
20     static NSString *firstCellID = @"first";
21     
22     //注册可重用cell
23     if (!_isRegistNib) {
24         NSLog(@"registernib");
25         UINib *nib = [UINib nibWithNibName:@"CustomTableCellDefaultView" bundle:nil];
26         [tableView registerNib:nib forCellReuseIdentifier:defaultCellID];
27         
28         UINib *nibFirst = [UINib nibWithNibName:@"HomeTableCellFirstView" bundle:nil];
29         [tableView registerNib:nibFirst forCellReuseIdentifier:firstCellID];
30         _isRegistNib = !_isRegistNib;
31     }
32     NSInteger sectionIndex = indexPath.section;
33     
34     
35     if (sectionIndex % 2 == 0) {
36         //如果是第一个区域,显示欢迎的cell
37         HomeTableCellFirst *cell = (HomeTableCellFirst *)[tableView dequeueReusableCellWithIdentifier:firstCellID forIndexPath:indexPath];
38         NSLog(@"创建第一个cell");
39         NSLog(@"cell的地址是:%@",cell);
40         NSLog(@"--------------------------------------");
41         return cell;
42     }
43     else if(sectionIndex % 2 == 1){
44         //如果是第二个区域,显示普通的cell
45         CustomTableCellDefault *cell = (CustomTableCellDefault *)[tableView dequeueReusableCellWithIdentifier:defaultCellID forIndexPath:indexPath];
46         NSLog(@"创建普通的cell");
47         NSLog(@"cell的地址是:%@",cell);
48         NSLog(@"--------------------------------------");
49         cell.lblStoreName.text = [NSString stringWithFormat:@"店家%ld",(indexPath.row+1)];
50         return cell;
51     }
52     else{return nil;}
53     
54     
55     
56 }
57 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
58 {
59     if (indexPath.section % 2 == 0) {
60         return 150;
61     }
62     return 80;
63 }
64 
65 -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
66 {
67     return 10;
68 }

上面的tableview实在ib中拖进去的,style时group

在代码中设置了section的数量是4,在- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

方法中,使用registerNib:forCellReuseIdentifier方法注册了两种自定义的cell,并且会打印cell的地址及其他信息,先来看下运行效果

ios基础之UITableViewCell的重用(带示例原创)第3张

刚打开view的时候,tableview一共加载了[cell1]一个,[cell2] 7个。

当我们继续向上滚动的时候,因为当前[cell2]的数量并不能充满整个window,所以还会继续创建cell2的对象,与此同时,唯一的一个cell1消失在window的时候,被tableview扔进了重用列表。

ios基础之UITableViewCell的重用(带示例原创)第4张

通过上面的图,看到nslog打印出来的cell指向的地址,很清楚,我们创建了7个不同的[cell2]对象

当继续滚动的时候,会继续打印出和上面地址不重复的[cell2],大家可以自己试试,我就不上图了

因为我让第三个section又显示了[cell1],所以继续向下滚动,当它出现时,控制台打印的cell的地址是0x7fbc2176c620,和第一个cell是同一个对象,因为使用了重用列表中的那个[cell1]的对象。

通过上面的实验,可以总结下面的结论:

使用重用机制后:

1、tableview至少会创建可视区域高度cell高度 个 cell对象,因为当第一个cell隐藏了一半时,意味着要还要创建一个新的cell

2、创建了足够多的cell后,再显示cell就会使用可重用队列中的cell

以上是本人自己的理解,如果不对的地方,还希望和大家多多交流。

 

免责声明:文章转载自《ios基础之UITableViewCell的重用(带示例原创)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇样本稳定指数PSICSS-三栏自适应高度下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

#应用openxml读写excel代码

这个例子比较简单,没有考虑格式之类的问题。 using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Spreadsheet; using System; using System.Collections.Generic; using System.IO; using Syst...

实验3- 熟悉常用的 HBase 操作

石家庄铁道大学信息科学与技术学院 实验报告 2018年----2019年第一学期 题目:熟悉常用的 HBase 操作 课程名称:大型数据库应用技术 班级:信1605-2班 姓名: XX学号: XXXXXXXX 指导教师: XXX 一、实验内容与完成情况:(实验具体步骤和实验截图说明) 实验...

AutoML综述更新 【AutoML:Survey of the State-of-the-Art】

论文: AutoML: Survey of the State-of-the-Art 下面这个网站会不断更新AutoML相关的论文,当然如果你的论文未被收录,你也可以手动上传你的论文让更多人看到: https://marsggbo.github.io/automl_a_survey_of_state_of_the_art/ 1、文章结构 下面是整个A...

不升级Element-UI 版本为时间选择器增加标记功能

Element-UI里的date-picker是个优秀的时间选择器,支持的选项很多,定制型很强。不过date-picker在2.12版本之前并不支持自定义单元格样式,也就是2.12的cellClassName功能。所以如果使用了2.12之前的版本,那么你就无法直接去更改单元格的样式了,因此在日历上就无法标记出重要日期(比如放假安排)。 公司项目里用的Ele...

iOS-高仿通讯录之商品索引排序搜索

概述 TableView添加右侧索引, 将数据按照索引分组排序, 并添加搜索功能且在搜索界面复用当前页面. 详细 代码下载:http://www.demodashi.com/demo/10696.html 项目中像一些商品搜索类界面, TableView添加右侧索引的使用越来越多, 的确用户体验提高了许多. 一、主要思路 大致思路: 1....

TableView之表头、表尾,区头、区尾!

一、UITableView的UITableViewStyle   样式分为UITableViewStylePlain和UITableViewStyleGrouped两种;   plain样式下区头和区尾是悬浮的(即拖动表的时候区头和区尾不会消失,一直显示在界面上);   grouped样式区头和区尾是随表一起滑动的。静态的tableview需要分区时(XI...