`
jishublog
  • 浏览: 872131 次
文章分类
社区版块
存档分类
最新评论

墨半成霜为你深入剖析UITableView SDK

 
阅读更多
UITableView大家平时用的太多太多了,但是大家是否都搞清楚UITableView内部的运行机制呢?
我想用一句话来概括UITableView:他是一个子视图可以重复使用的特殊的UIScrollView。大家说对不对呢?

首先我们看下一段头文件声明:

<script src="https://code.csdn.net/snippets/760.js" type="text/javascript"></script>




看重点,首先UITableView是UIScrollView的子类,也就是说UIScrollView的所有属性和方法UITableView都能使用。其次UITableView扩展了两个协议,UITableViewDelegate和UITableViewDatasource。顾名思义后面的协议是用来委托给某个控制器来使其帮助我们管理tableview所展示的数据的。

所以一点某个控制器接受了这个tableView就必须实现这两个协议里面的@requried协议:


<script src="https://code.csdn.net/snippets/761.js" type="text/javascript"></script>


所以说无论如何,如果tableview的控制器没有实现这个协议,那么APP直接就会崩溃。如果没有崩溃,那肯定是你没有tableview setDelegate:xxxController


而在这两个必须协议中,第一个协议仅仅是需要我们返回一个NSInteger来告诉tableview每个section里面的cell个数。而第二个协议可谓是与我们天天打交道了。我称之为tableview的灵魂方法。
就是在这个方法里面,我们要研究他究竟是如何来实现子视图重用的。
首先 常规写法,创建一个控制器,声明这2个协议(声明不会帮你完成委托这个动作,只是告诉编译器 而且方便你自己自动联想,还是得自己去setDelegate)



<script src="https://code.csdn.net/snippets/762.js" type="text/javascript"></script>



然后在controller中实现必须实现的协议:
<script src="https://code.csdn.net/snippets/763.js" type="text/javascript"></script>





OK,这个短小精悍的常规写法包含了太大的信息量了,我们不妨在重用失败的那一行打个断点:

注意 cell指针指向的地址是0x00000000
说明[tableView dequeueReusableCellWithIdentifier:reuseIdentifier]方法给他返回了一个nil。
从字面上来理解,这个函数的语义是:根据特定的标示符来分配可重用的单元格。所以返回为nil,那么我们可以认为在这个tableView当中,这个特定的标示符@"objcoder"暂时还没有可以重用的单元格以供分配。
OK 我们继续执行,为了更好的观察cell重用失败的次数,我们不妨做如下修改:

<script src="https://code.csdn.net/snippets/764.js" type="text/javascript"></script>



运行一下,控制台会输出:
2013-08-21 23:31:02.991 TableViewDemo[17213:c07] 重用的次数1
2013-08-21 23:31:03.865 TableViewDemo[17213:c07] 重用的次数2
2013-08-21 23:31:04.354 TableViewDemo[17213:c07] 重用的次数3
2013-08-21 23:31:04.888 TableViewDemo[17213:c07] 重用的次数4
2013-08-21 23:31:05.352 TableViewDemo[17213:c07] 重用的次数5
2013-08-21 23:31:05.722 TableViewDemo[17213:c07] 重用的次数6
2013-08-21 23:31:06.127 TableViewDemo[17213:c07] 重用的次数7
2013-08-21 23:31:06.727 TableViewDemo[17213:c07] 重用的次数8
2013-08-21 23:31:07.216 TableViewDemo[17213:c07] 重用的次数9
2013-08-21 23:31:07.623 TableViewDemo[17213:c07] 重用的次数10
2013-08-21 23:31:08.139 TableViewDemo[17213:c07] 重用的次数11


一共20个cell,那么我们第一次运行alloc init 了11次,第一个画面才出来:
不难发现,截图中,当前屏幕一共有10个半cell,那么他分配了11个出来,这个很好理解,不可能给你分配半个cell让你用吧。
这个时候我们再往下滚:


2013-08-21 23:31:08.139 TableViewDemo[17213:c07] 重用的次数11
2013-08-21 23:32:14.779 TableViewDemo[17213:c07] 重用的次数12



在第11次log后面仅仅多出来了一个12,然后我把20个cell滚动完,发现没有再进入alloc init 语句。这个也很好理解,下面第12cell出现一点点的时候,第一个cell还没有彻底出屏幕呢。
所以这里我们可以看到tableView的特性,可以理解为一个大学生的心路旅程:
1.什么时候读大学,什么找房子
2.什么时候找到房子,什么时候往房子里面放行李
3.先找大四毕业的同学看看有没有很便宜的房子(很便宜 我们这里抽象为不要钱)
4.自己是学校的第一届学生,或者大四学长的房子都已经转出去住人了,或者自己是1月份入学的,这个时候还没人毕业呢,只好自己去租很贵的新房子
5.自己毕业了,房子也可以再次转租给学弟学妹了,但是行李得带走!

所以我们要换位思考,如果我们自己就是这个cell,当我们还没有读大学的时候,有多少同学会提前把房子找好?所以这是什么时候读大学,什么时找房子特性
其次行李必须放在自己房子里,不能外面到处摆,这是第二个特性
其三如果有便宜到几乎不要钱的房子,你会不会去租一万块钱一个月的房子?这是有限重用原则
其四如果真的没有便宜的房子,你是第一届大学生,或者这个时候真的不是毕业季,条件不允许的情况下,你除非不读大学了,你只要想读大学(进入我们这个屏幕显示区域),那你是不是该老老实实掏钱?这是重用失败后的下下策
其五,你毕业了,你换位思考你的学弟学妹现在跟你一样的心情,你应该给他们重用的便利,但是你的行李会带走,而他们会带来他们的行李,房子是那个房子,东西不再一样了。

仔细分析,前面11个数据源,他们是一起来学校开学的,那么之前没有学长,遵循原则4,他们必须老老实实掏钱。
当第12个学生入学的时候,可能是4月份,第一个学生答辩快完了,但是还没有完,学生12遵循原则4,还是要老老实实掏钱。
学生13现在正在读高三,他才不会想读大学的事情呢,所以遵循原则1,他这个时候根本就不会去联系租房中介(tableView)关于房子的事情;
当第13个学生入学的时候,可能是7月份,学生1已经毕业了,房子空出来了,所以学生13遵循原则3,他去转手了学生1的房子。此时学生1的行李已经一起带走了(cell上面的文字,图片内容等,可以不带走,显示地做一个set nil处理更符合我们这里的比喻,也使你的内容更不容易紊乱),学生13带着他自己的行李住进了学生1的房子。

如果反过来,我们往下滑再划回去,可以理解为学生13毕业后,房子空出来了,但是这个时候学生1又回来学校教书了,他又需要房子了,遵循原则3,他这个时候就不需要去买贵房子了。
所以我们得出一个张氏定理:
给定一所能容纳N个学生的不提供住宿的且入学时间和毕业时间有时间差的大学,仅需要N+1所房子就能减少所有学生的开支。
(第一批的N个学生必须得老老实实掏钱租N所房子,第N+1个学生入学,由于入学时间差他必须多租一所房子,而后面的学生也因为这个时间差一对一的获得了一所可中专的房子)

TableView,就是一个房屋中介。



分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics