UITableview delegate dataSource调用探究
UITableview是大家常用的UIKit组件之一,使用中我们最常遇到的就是对delegate和dataSource这两个委托的使用。我们大多数人可能知道当reloadData这个方法被调用时,delegate和dataSource就会被回调,但是其中具体的细节,可能很多人不会去探究。
我最近有兴趣来探讨这个问题是因为我最近遇到过dataSource中有的方法被调用,但是有的方法没有被调用的情况,同时你会发现当tableview被add到一个superView的时候,也会触发了reloadData一样的回调。那么这两个委托究竟是怎么执行的呢?
我们首先来看看苹果文档对reloadData的描述
Call this method to reload all the data that is used to construct the table,
including cells, section headers and footers, index arrays, and so on. For
efficiency, the table view redisplays only those rows that are visible. It adjusts
offsets if the table shrinks as a result of the reload. The table view’s delegate or
data source calls this method when it wants the table view to completely reload
its data. It should not be called in the methods that insert or delete rows,
especially within an animation block implemented with calls to beginUpdates and
endUpdates.大致的意思就是说reload这个方法是用来构建table的,包括cell、section,而且只会对可见的行进行重新的绘制,当tableview想要完整的加载数据时,delegate和data source会调用此方法。增加删除行,尤其是需要block动画的时候不用用它。
从这里只能看出个大概,并没有解释调用的原理。那么让我们先写一个最基本的tableview实现,然后对delegate和data source的回调设置一下断点看看。
- (void)viewDidLoad {
[super viewDidLoad];
UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(, , self.view.bounds.size.width, self.view.bounds.size.height)];
tableView.delegate = self;
tableView.dataSource = self;
[self.view addSubview:tableView];
// [tableView reloadData];
// [tableView layoutSubviews];
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return ;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return ;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return ;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellID = @"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if(!cell){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
cell.textLabel.text = @"哈哈";
return cell;
}
我们先对下面这四个方法设置一下断点,然后观察左边的栈信息。
首先被调用的是numberOfSectionsInTableView:
我们可以看到从addSubview是如何一步步调用到numberOfSectionsInTableView:的。
好的,我们下一步看断点断到了tableView:numberOfRowsInSection:上。
_rebuildGeometry这个私有方法之前都是一样的,所以我这里并没有全截,可以看到_rebuildGeometry中不仅调用了_updateRowData,还调用了一个_updateContentSize,从这里来获得每个section的行数。
我们接着往下看,到了tableView:heightForRowAtIndexPath:
这里通过了一个block回调的方式获取了各个row的高度,并决定了整个section的高度。
然后我们会发现,以上的几个方法还会再被调用一遍:
但是栈信息已经不一样了,这次调用时由于tableview调用了layoutSubviews,而reloadData是layoutSubviews里调用的一个方法,因为layoutSubviews也是个公有的方法,所以我们可以用它来触发reloadData。
断点继续执行,就执行到了tableView: cellForRowAtIndexPath:,我们用它来获取tableview每个row的cell。
我们会发现tableView: cellForRowAtIndexPath:并不是靠_rebuildGeometry下面的方法来触发,而只是靠layoutSubviews来触发,如果layoutSubviews没有执行成功,那么就可能会遇到我之前遇到过的前几个方法执行而tableView: cellForRowAtIndexPath:不执行的问题。
- 多了解UIKit的栈信息能够帮我们了解苹果运行的机制和原理,从而帮我们解决一些看起来非常诡异的bug,多看看苹果的私有方法也有助于我们养成良好的编程习惯,我们尽量模仿苹果的代码规范无论是对自己写代码看着舒服,还是对他人来读我们写的代码都一件好事。
UITableview delegate dataSource调用探究的更多相关文章
- Swift_TableView(delegate,dataSource,prefetchDataSource 详解)
Swift_TableView(delegate,dataSource,prefetchDataSource 详解) GitHub import UIKit let identifier = &quo ...
- C# Delegate 异步调用
namespace ConsoleApplication22 { /// /// 异步操作 /// /// /// /// //internal Func<int,int,int> int ...
- UITableView 接口的调用顺序
ios7启用estimatedHeightForRowAtIndexPath之后的api调用顺序called -[XHYTableViewController tableView:heightForR ...
- 快速设置UITableView不同section对应于不同种类的cell
快速设置UITableView不同section对应于不同种类的cell 本文主要是为了写明如何在UITableView中,一个section对应于一种类型的cell,写起来不凌乱. 在不封装任何类的 ...
- 解决tableView中cell动态加载控件的重用问题
解决tableView中cell动态加载控件的重用问题 tableView的cell,有时候需要在运行时取得对应的数据后才能够动态的创建该cell中的控件并加载到该cell中,此时,你一定会遇到重用问 ...
- 更新tableView的某个cell
更新tableView的某个cell 异步加载完数据后更新某个cell,这应该是非常常见的使用方法了,我们经常会用reloadData. 效果: 源码: // // RootViewControlle ...
- iOS基础 - UITableView的数据源(dataSource)和代理(delegate)
UITableView的数据源(dataSource)和代理(delegate) UITableView需要一个数据源(dataSource)来显示数据,UITableView会向数据源查询一共有多少 ...
- 教你写能被舒服舒服又舒服地调用的iOS库
目录 前言 脑洞开一开 分析 整容 结语 前言 2014年过的那么快,过年又那么块,2015年又是飞快地节奏,真尼玛感觉上帝是不是无聊使用了变速外挂开启了加速模式~到现在博主都无法接受已经上班的事实… ...
- iOS应用架构谈(三):View层的组织和调用方案(下)
iOS客户端应用架构看似简单,但实际上要考虑的事情不少.本文作者将以系列文章的形式来回答iOS应用架构中的种种问题,本文是其中的第二篇,主要讲View层的组织和调用方案.下篇主要讨论做View层架构的 ...
随机推荐
- 一步步开发自己的博客 .NET版(1、基本显示)
前言 我们每个猿都有一个搭建自己独立博客的梦,我也不例外.以前想 现在想 以后也想.之所以一直迟迟没有着手,是因为难以跨出第一步.每次心里想着,等我以后技术好了再说,然后就没有然后了.以前用过word ...
- X Window 的奥秘
大名鼎鼎的 X Window 大家肯定不陌生.都知道它是 Unix/Linux 下面的窗口系统,也都知道它基于 Server/Clinet 架构.在网上随便搜一搜,也可以找到不少 X Window 的 ...
- Android开发学习之路-关于Exception
Exception在Java中是表示异常的一个类.它是Throwable的子类. 而Exception的子类RuntimeException是一个特殊的异常类,在代码中不需要对此类进行throw,而是 ...
- ASP.NET OAuth:access token的加密解密,client secret与refresh token的生成
在 ASP.NET OWIN OAuth(Microsoft.Owin.Security.OAuth)中,access token 的默认加密方法是: 1) System.Security.Crypt ...
- 前端CSS部分知识整理
1.如何清除图片下方出现几像素的空白间隙? /*方法1:*/ img{display:block;} 方法2: /*img{vertical-align:top;}*/ 2.如何让文本垂直对齐文本输入 ...
- 用CIL写程序:写个函数做加法
前言: 上一篇文章小匹夫为CIL正名的篇幅比较多,反而忽略了写那篇文章初衷--即通过写CIL代码来熟悉它,了解它.那么既然有上一篇文章做基础(炮灰),想必各位对CIL的存在也就释然了,兴许也燃起了一点 ...
- ASP.NET Core 中文文档 第二章 指南(4.10)检查自动生成的Detail方法和Delete方法
原文 Examining the Details and Delete methods 作者 Rick Anderson 翻译 谢炀(Kiler) 校对 许登洋(Seay).姚阿勇(Mr.Yao) 打 ...
- Windows Phone Toolkit 的 DatePicker 控件本地化的问题
用到 The Windows Phone Toolkit 里的 DatePicker 控件,但是多语言的时候出现了问题: 手机设置为中文,虽然月份跟星期有效,但是 Title 却还是默认的语言:CHO ...
- iOS 编辑UITableView(根据iOS编程编写)
上个项目我们完成了 JXHomepwner 简单的应用展示,项目地址.本节我们需要在上节项目基础上,增加一些响应用户操作.包括添加,删除和移动表格. 编辑模式 UITableView 有一个名为 e ...
- 在Ubuntu|CentOS上安装Shutter截图工具及快捷键设置
简介 Shutter前身叫GScrot,它是一款相当棒的截图软件. 通过Shutter,你可以截取包括选定区域.全屏幕.窗口.窗口内的控件甚至网页的图像.通过内置的强大插件机制,你可以在截图后,对图像 ...