阿峥教你实现UITableView循环利用
2015-08-26 16:32
288 查看
前言
大家都知道UITableView,最经典在于循环利用,这里我自己模仿UITableView循环利用,写了一套自己的TableView实现方案,希望大家看了我的文章,循环利用思想有显著提升。
效果如图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201509/a9513aef898a67ce29006d88b70328bb.gif)
研究UITableView底层实现
1.系统UITabelView的简单使用,这里就不考虑分组了,默认为1组。
2.验证UITabelView的实现机制。
如图打印结果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201509/8a2e951565b759cce0326c62182d2735.png)
分析:底层先获取有多少cell(10个),在获取每个cell的高度,返回高度的方法一开始调用10次。
目的:确定tableView的滚动范围,一开始计算所有cell的frame,就能计算下tableView的滚动范围。
分析:tableView:cellForRowAtIndexPath:方法什么时候调用。
打印验证,如图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201509/be61128a48959ad7f896e2fe3b4268db.png)
一开始调用了7次,因为一开始屏幕最多显示7个cell
目的:一开始只加载显示出来的cell,等有新的cell出现的时候会继续调用这个方法加载cell。
3.UITableView循环利用思想
当新的cell出现的时候,首先从缓存池中获取,如果没有获取到,就自己创建cell。
当有cell移除屏幕的时候,把cell放到缓存池中去。
二、自定义UIScroolView,模仿UITableView循环利用
1.提供数据源和代理方法,命名和UITableView一致。
2.提供代理和数据源属性
警告:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201509/a167a49a6b09367f26a0f11000dca1d3.png)
解决,在YZTableView.m的实现中声明。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201509/7264f12d08507b568c2d566bb567f285.png)
原因:有人会问为什么我要定义同名的delegate属性,我主要想模仿系统的tableView,系统tableView也有同名的属性。
思路:这样做,外界在使用设置我的tableView的delegate,就必须遵守的我的代理协议,而不是UIScrollView的代理协议。
3.提供刷新方法reloadData,因为tableView通过这个刷新tableView。
4.实现reloadData方法,刷新表格
回顾系统如何刷新tableView
1).先获取有多少cell,在获取每个cell的高度。因此应该是先计算出每个cell的frame.
2).然后再判断当前有多少cell显示在屏幕上,就加载多少
5.如何判断cell显示在屏幕上
当tableView内容往下走
![](https://oscdn.geek-share.com/Uploads/Images/Content/201509/35d40a19b05854e4596803067ed49943.gif)
当tableView内容往上走
![](https://oscdn.geek-share.com/Uploads/Images/Content/201509/6c189b2bcd18582d16f06065e5ee66ae.gif)
6.在滚动的时候,如果有新的cell出现在屏幕上,先从缓存池中取,没有取到,在创建新的cell.
分析:
需要及时监听tableView的滚动,判断下有没有新的cell出现。
大家都会想到scrollViewDidScroll方法,这个方法只要一滚动scrollView就会调用,但是这个方法有个弊端,就是tableView内部需要作为自身的代理,才能监听,这样不好,有时候外界也需要监听滚动,因此自身类最好不要成为自己的代理。(设计思想)
解决:
重写layoutSubviews,判断当前哪些cell显示在屏幕上。
因为只要一滚动,就会修改contentOffset,就会调用layoutSubviews,其实修改contentOffset,内部其实是修改tableView的bounds,而layoutSubviews刚好是父控件尺寸一改就会调用.具体需要了解scrollView底层实现。
思路:
判断下,当前tableView内容往上移动,还是往下移动,如何判断,取出显示在屏幕上的第一次cell,当前偏移量 > 第一个cell的y值,往下走。
需要搞个数组记录下,当前有多少cell显示在屏幕上,在一开始的时候记录.
往下移动
1.如果已经滚动到tableView内容最底部,就不需要判断新的cell,直接返回.
2.需要判断之前显示在屏幕cell有没有移除屏幕
3.只需要判断下当前可见cell数组中第一个cell有没有离开屏幕
4.只需要判断下当前可见cell数组中最后一个cell的下一个cell显没显示在屏幕上即可。
往上移动
1.如果已经滚动到tableView最顶部,就不需要判断了有没有心的cell,直接返回.
2.需要判断之前显示在屏幕cell有没有移除屏幕
3.只需要判断下当前可见cell数组中最后一个cell有没有离开屏幕
4.只需要判断下可见cell数组中第一个cell的上一个cell显没显示在屏幕上即可
注意点:如果可见cell数组中第一个cell的上一个cell显示到屏幕上,一定要记得是插入到可见数组第0个的位置。
问题1:
判断下当前可见cell数组中最后一个cell的下一个cell显没显示在屏幕上
这里需要计算下一个cell的frame,frame就需要计算下一个cell的y值,需要获取对应的cell的高度 cellY = lastCellY + cellH
而高度需要根据indexPath,从数据源获取
解决:
可以搞个字典记录每个可见cell的indexPath,然后获取对应可见的indexPath,就能获取下一个indexPath.
注意:
当cell从缓存池中移除,一定要记得从可见数组cell中移除,还有可见cell的indexPath也要移除.
7.缓存池搭建,缓存池其实就是一个NSSet集合。
搞一个NSSet集合充当缓存池.
cell离开屏幕,放进缓存池
提供从缓存池获取方法,从缓存池中获取cell,记住要从NSSet集合移除cell.
8.tableView细节处理
原因:刷新方法经常要调用
解决:每次刷新的时候,先把之前记录的全部清空
如果你喜欢这篇文章,可以继续关注我,微博:吖了个峥,欢迎交流。
点击这下载源代码。
大家都知道UITableView,最经典在于循环利用,这里我自己模仿UITableView循环利用,写了一套自己的TableView实现方案,希望大家看了我的文章,循环利用思想有显著提升。
效果如图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201509/a9513aef898a67ce29006d88b70328bb.gif)
研究UITableView底层实现
1.系统UITabelView的简单使用,这里就不考虑分组了,默认为1组。
如图打印结果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201509/8a2e951565b759cce0326c62182d2735.png)
分析:底层先获取有多少cell(10个),在获取每个cell的高度,返回高度的方法一开始调用10次。
目的:确定tableView的滚动范围,一开始计算所有cell的frame,就能计算下tableView的滚动范围。
分析:tableView:cellForRowAtIndexPath:方法什么时候调用。
打印验证,如图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201509/be61128a48959ad7f896e2fe3b4268db.png)
一开始调用了7次,因为一开始屏幕最多显示7个cell
目的:一开始只加载显示出来的cell,等有新的cell出现的时候会继续调用这个方法加载cell。
3.UITableView循环利用思想
当新的cell出现的时候,首先从缓存池中获取,如果没有获取到,就自己创建cell。
当有cell移除屏幕的时候,把cell放到缓存池中去。
二、自定义UIScroolView,模仿UITableView循环利用
1.提供数据源和代理方法,命名和UITableView一致。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201509/a167a49a6b09367f26a0f11000dca1d3.png)
解决,在YZTableView.m的实现中声明。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201509/7264f12d08507b568c2d566bb567f285.png)
原因:有人会问为什么我要定义同名的delegate属性,我主要想模仿系统的tableView,系统tableView也有同名的属性。
思路:这样做,外界在使用设置我的tableView的delegate,就必须遵守的我的代理协议,而不是UIScrollView的代理协议。
3.提供刷新方法reloadData,因为tableView通过这个刷新tableView。
回顾系统如何刷新tableView
1).先获取有多少cell,在获取每个cell的高度。因此应该是先计算出每个cell的frame.
2).然后再判断当前有多少cell显示在屏幕上,就加载多少
当tableView内容往下走
![](https://oscdn.geek-share.com/Uploads/Images/Content/201509/35d40a19b05854e4596803067ed49943.gif)
当tableView内容往上走
![](https://oscdn.geek-share.com/Uploads/Images/Content/201509/6c189b2bcd18582d16f06065e5ee66ae.gif)
分析:
需要及时监听tableView的滚动,判断下有没有新的cell出现。
大家都会想到scrollViewDidScroll方法,这个方法只要一滚动scrollView就会调用,但是这个方法有个弊端,就是tableView内部需要作为自身的代理,才能监听,这样不好,有时候外界也需要监听滚动,因此自身类最好不要成为自己的代理。(设计思想)
解决:
重写layoutSubviews,判断当前哪些cell显示在屏幕上。
因为只要一滚动,就会修改contentOffset,就会调用layoutSubviews,其实修改contentOffset,内部其实是修改tableView的bounds,而layoutSubviews刚好是父控件尺寸一改就会调用.具体需要了解scrollView底层实现。
思路:
判断下,当前tableView内容往上移动,还是往下移动,如何判断,取出显示在屏幕上的第一次cell,当前偏移量 > 第一个cell的y值,往下走。
需要搞个数组记录下,当前有多少cell显示在屏幕上,在一开始的时候记录.
1.如果已经滚动到tableView内容最底部,就不需要判断新的cell,直接返回.
2.需要判断之前显示在屏幕cell有没有移除屏幕
3.只需要判断下当前可见cell数组中第一个cell有没有离开屏幕
4.只需要判断下当前可见cell数组中最后一个cell的下一个cell显没显示在屏幕上即可。
1.如果已经滚动到tableView最顶部,就不需要判断了有没有心的cell,直接返回.
2.需要判断之前显示在屏幕cell有没有移除屏幕
3.只需要判断下当前可见cell数组中最后一个cell有没有离开屏幕
4.只需要判断下可见cell数组中第一个cell的上一个cell显没显示在屏幕上即可
注意点:如果可见cell数组中第一个cell的上一个cell显示到屏幕上,一定要记得是插入到可见数组第0个的位置。
判断下当前可见cell数组中最后一个cell的下一个cell显没显示在屏幕上
这里需要计算下一个cell的frame,frame就需要计算下一个cell的y值,需要获取对应的cell的高度 cellY = lastCellY + cellH
而高度需要根据indexPath,从数据源获取
解决:
可以搞个字典记录每个可见cell的indexPath,然后获取对应可见的indexPath,就能获取下一个indexPath.
当cell从缓存池中移除,一定要记得从可见数组cell中移除,还有可见cell的indexPath也要移除.
搞一个NSSet集合充当缓存池.
cell离开屏幕,放进缓存池
提供从缓存池获取方法,从缓存池中获取cell,记住要从NSSet集合移除cell.
原因:刷新方法经常要调用
解决:每次刷新的时候,先把之前记录的全部清空
点击这下载源代码。
相关文章推荐
- POJ 2081 Recaman's Sequence(水~)
- Arduino 3g shield using GSM bought from ITead
- UItextField
- Android UI设计:ExpandableListView
- POJ 2479 Maximum sum && 2593 Max Sequence (dp)买一送一
- UISwitch
- 详细解析BluetoothAdapter的详细api
- 循环结构中break、continue、return和exit的区别
- easyui panel自适应问题
- BLToolkit : Table-value functions
- Android UI设计:Gallery
- UIStepper
- 72.UITableView:改变 TableHeaderView 的高度
- Office 365 IT Professional ——配置Anonymous Guest Links
- 二分+树状数组/线段树(区间更新) HDOJ 4339 Query
- easyui 绑定数据
- Jesque 基础入门
- Builder
- 不要随便使用 runAllManagedModulesForAllRequests="true" 来解决问题
- iPhone开发之UIScrollView滚动组件的使用(一) 拖线实现——大图的移动展示