一、UITableView概述
UITableView继承自UIScrollView,可以表现为Plain和Grouped两种风格。
UITableView有两个Delegate分别为:dataSource和delegate。
·dataSource是UITableViewDataSource类型,主要为UITableView提供显示用的数据(UITableViewCell),指定UITableViewCell支持的编辑操作类型(insert,delete和reordering),并根据用户的操作进行相应的数据更新操作,如果数据没有更具操作进行正确的更新,可能会导致显示异常,甚至crush。
·delegate是UITableViewDelegate类型,主要提供一些可选的方法,用来控制tableView的选择、指定section的头和尾的显示以及协助完成cell的删除和排序等功能。
(其中UITableView声明了一个NSIndexPath的类别,主要用来标识当前cell的在tableView中的位置,该类别有section和row两个属性,前者标识当前cell处于第几个section中,后者代表在该section中的第几行。)
UITableView只能有一列数据(cell),且只支持纵向滑动,当创建好的tablView第一次显示的时候,我们需要调用其reloadData方法,强制刷新一次,从而使tableView的数据更新到最新状态。
二.UITableView的数据源
· UITableView是依赖外部资源为新表格单元填上内容的,我们称为数据源,这个数据源可以根据索引路径提供表格单元格,在UITableView中,索引路径是NSIndexPath的对象,可以选择分段或者分行,即是我们编码中的section和row。
· UITableView有三个必须实现的核心方法,分别如下:
-(NSInteger)numberOfSectionsInTableView:(UITableView*)tableView;
这个方法可以分段显示或者单个列表显示我们的数据。这个方法的参数是UITableView*,也就是说,我们允许在一个View中有若干个Table View,可以为每个Table View分别设定section的数量。
-(NSInteger)tableView:(UITableView*)tableViewnumberOfRowsInSection:(NSInteger)section;
这个方法返回每个分段的行数,不同分段返回不同的行数可以用switch来做,如果是单个列表就直接返回单个你想要的函数即可。这里有两个参数,第一个是UITableView*,第二个是section的index。也就是说它可以指定某个table view中的某个section的行数。
-(UITableViewCell*)tableView:(UITableView*)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath;
这个方法来返回Table View中每一行(每一个cell)的内容。它有两个参数,第一个是UITableView*,第二个是IndexPath*。IndexPath包含了该行所在的section的序号和它的行序号。我们可以通过[indexPath section]和[indexPath row]就可以得到该单元所在的section序号和行序号。
·因为每一行唯一的区别就是显示的文本不同,所以为了节约资源,iPhone允许我们重用UITableViewCell的资源,这就是ios中的重用机制。
四.UITableView的委托方法
UITableView实例使用委托是为了响应用户的交互动作。委托告知表格将响应这些交互的责任移交给指定对象。这个指定的对象通常是拥有表格视图的UITableViewController控制器对象。当然该委托必须实现UITableViewDelegate协议。其委托方法基本上定制表格结构的:(这些方法都是optional)
tableView:heightForRowAtIndexPath 返回指定的row的高度。
tableView:heightForHeaderInSection 返回指定分段的header view区域的高度。
tableView:heigthForFooterInSection 返回指定分段的footer view区域的高度。
tableView:titleForHeaderInSection 返回指定分段的header的title,如果这个section header有返回view,那么title就不起作用。
tableView:viewForHeaderInSection 返回指定分段的header的view,若没有,则可以不返回view。
tableView:didSelectRowAtIndexPath 当用户选中某个行的cell的时候,回调用这个。前提是必须设置tableView的一个allowsSelection属性为YES才行。
tableView:accessoryButtonTappedForRowWithIndexPath 响应用户点击cell右边的箭头事件。
tableView:commitEditingStyle: editingStyleforRowAtIndexPath 通知用户编辑了哪个cell。
五.UITableView的各方法执行情况
从我运行程序的显示分析,数据源和委托方法的调用顺序不是固定的,是要根据方法的不同而不同,但是是一种有规律的执行。大概如下:
• 1.保存完毕TabelView中添入的数据
• 2."numberOfSectionsInTableView:"返回TableView的section数目
• 3."tableView:titleForHeaderInSection:"section1是否有表头标题栏
• 4."tableView:numberOfRowsInSection:"设置section1中行数
• 5."tableView:heightForRowAtIndexPath:"设置section1中row1行的高度……row2行的高度……逐行设置,直至当前section1属性设置完毕
• 7."tableView:titleForHeaderInSection:"section2是否有表头栏,之后同4-5,设置section2的属性.同理,设置完毕所有的section的相关属性
• 8."tableView:cellForRowAtIndexPath:"接下来设置的是每个section中每row添加的数据
这样整个TableView就设置完毕了.
当选中可变的TableCell时,
• 1."tableView:willSelectRowAtIndexPath:"判断是否为可变TableCell
• 2."tableView:didSelectRowAtIndexPath:"保存选中的TableCell的信息,同时reload当前的TableView.重新执行上面描述的TableView载入的过程。
六、UITableViewCell重用机制
- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [table dequeueReusableCellWithIdentifier:@"FlipsideCellIdentifier"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero
reuseIdentifier:@"FlipsideCellIdentifier"] autorelease];
}
cell.text = [soundSignatures objectAtIndex:indexPath.row];
return cell;
}
理解:
每一个UITableView里都维护着一个cell队列,当UITableView刚加载的时候,cell队列里是没有任何数据的。所以就有if(cell==nil)
dequeueResableCellWithIdentifier从字面上理解就是”出列可重用的cell",也就是根据一个标识identifier从cell队列里取出一个
UITableViewCell,当然了,如果cell队列里没有此标识的cell,调用此方法的结果就是返回nil。因此,在UITableView刚加载的时候,cell队列里没有可用的cell,所以必须通过语句
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
来创建对应CellIdentifier标识的UITableViewCell实例。
[ tableView:cellForRowAtIndexPath:方法主要是根据nsindex取得一个cell ]
而当UITableView在滚动的时候导致UITableViewCell滚出手机屏幕视图的时候,程序会将这一个UITalbeViewCell实例放入此UITableView所维护的cell队列中。当UITableview中有新的UITableViewCell需要展现在手机屏幕视图上时,就会调用tableView:cellForRowAtIndexPath:方法了。
因此我们可以知道以下几点:
1-重取出来的cell是有可能已经捆绑过数据或者加过子视图的,所以,如果有必要,要清除数据(比如textlabel的text)和remove掉add过的子视图(使用tag)。
2-这样设计的目的是为了避免频繁的 alloc和delloc
cell对象而已,没有多复杂。
3-设计的关键是实现cell和数据的完全分离
如果不想重用UITableViewCell实例,如在一个每一行都显示不同内容的UITableView实例时,我们可以用如下的方法:
NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%d%d",
[indexPath section], [indexPath row]];
来重新定义标识。
这样每一行都有其对应的identifier,从cell队列里取出来只有两个结果:
1-cell队列里没有此identifier对应的UITableViewCell实例,返回nil
2-cell队列里有此identifier对应的UITableViewCell实例,而且不会有重用到其他不同行的cell的情况