UITableView
是iOS开发中最常用的控件,也是UIKit中相对较难的.
在MVC模型中,UITableView
属于模型中的V.
MVC
- 模型(Model):负责存储数据,与用户界面无关
- 视图(View):负责显示界面,与模型无关
- 控制器(Controller):负责确保视图对象和模型对象保持一致
概述
UITableView
继承自UIScrollView
,可以竖直方向上滚动,UITableView有两种风格,分别是UITableViewStylePlain
和UITableViewStyleGrouped
UITableViewStyleGrouped
UITableView有两个Delegate分别为:dataSource和delegate:
- dataSource:需要实现UITableViewDataSource协议.主要为UITableView提供数据来源和提供Row的cell视图
- delegate:需要实现UITableViewDelegate协议.提供了Header/Footer的自定义View和高度,和选中动作的回调等.
在MVC中,提供数据给TableView的models是一个二维数组,由section和row组成,每条数据使用一个NSIndex来定位.
NSIndex
的第一维表示section,第二维表示row.UITableViewController
UITableViewController是系统提供的一个便利类,主要是为了方便我们使用UITableView,该类生成的时候就将自身设置成了其包含的tableView的dataSource和delegate,并创建了很多代理函数的框架.UITableViewController可以扮演MVC中的所有角色,我们可以通过其tableView属性获取该controller内部维护的tableView对象.
UITableViewController和UITableView的关系UITableViewCell
UITableView
中显示的每一个单元都是一个独立的视图对象,这些视图对象就是UITableViewCell
.
考虑到实际开发中cell可能会有很多,频繁生成cell对象是比较费时的,而且一次性生成所有cell对象可能占用太多内存.可以用以下方式来解决:
- 只生成能看到的Cell-->解决了速度问题
- 相似的行可以共用Cell-->解决了内存问题
我们会发现其初始化函数-initWithStyle:reuseIdentifier:
比较特别,跟我们平时看到的UIView
的初始化函数不同.因为这里引入了cell的重用机制.reuseIdentifier
就是指定重用的cell的布局的.相同的reuseIdentifier的cell会放在一个cell对象池中.
系统提供的UITableView也包含了四种风格的布局,分别是:
typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
UITableViewCellStyleDefault, // 左侧显示textLabel(不显示detailTextLabel),imageView可选(显示在最左边)
UITableViewCellStyleValue1, // 左侧显示textLabel、右侧显示detailTextLabel(默认蓝色),imageView可选(显示在最左边)
UITableViewCellStyleValue2, // 左侧依次显示textLabel(默认蓝色)和detailTextLabel,imageView可选(显示在最左边)
UITableViewCellStyleSubtitle // 左上方显示textLabel,左下方显示detailTextLabel(默认灰色),imageView可选(显示在最左边)
};
数据源
系统默认的四种风格
系统提供的四种并不能满足所有需求,有的时候我们需要定制自己的cell.
UITableViewCell
对象有一个子视图contenView
,
定制自己的cell有两种方法:
- 直接在contentView上添加子view:该方法可以在系统默认的几种cell上添加自己需要的view
- 从UITableViewCell中派生一个类:该方法可以深度定制自己的view,也可以指定cell在进入edit模式的时候如何相应等等.
观看这两种定制cell的方法,我们会发现subView都是添加在cell的contentView上面的,而不是直接加到cell上面,这样写也是有原因的。下面我们看一下cell在正常状态下和编辑状态下的构成图:
正常状态下:
编辑模式下:
通过观察上面两幅图片我们可以看出来,当cell在进入编辑状态的时候,contentView会自动的缩放来给Editing control腾出位置。这也就是说如果我们把subView添加到contentView上,如果设置autoresizingMask为更具父view自动缩放的话,cell默认的机制会帮我们处理进入编辑状态的情况。而且在tableView是Grouped样式的时候,会为cell设置一个背景色,如果我们直接添加在cell上面的话,就需要自己考虑到这个背景色的显示问题,如果添加到contentView上,则可以通过view的叠加帮助我们完成该任务。综上,subView最好还是添加到cell的contentView中。
编辑
UITableView
有一个editing
属性,如果将该属性设置为YES
.UITableView就会进入编辑模式.在编辑模式下,用户可以对UITableView中的cell进行添加,删除和移动等功能.
增加&删除
cell的delete和insert操作大部分流程都是一样的,当进入编辑模式的时候具体的显示是delete还是insert取决与该cell的editingStyle
的值,editStyle
的定义如下:
typedef enum {
UITableViewCellEditingStyleNone,
UITableViewCellEditingStyleDelete,
UITableViewCellEditingStyleInsert
} UITableViewCellEditingStyle;
当tableView进入编辑模式以后,cell上面显示的delete还是insert除了跟cell的editStyle
有关,还与 tableView的delegate的tableView:editingStyleForRowAtIndexPath:
方法的返回值有关
delete和insert的流程如下苹果官方文档中给出的图所示:
移动
为了使UITableVeiew进入edit模式以后,如果该cell支持reordering的话,reordering控件就会临时的把accessaryView
覆盖掉。为了显示reordering控件,我们必须将cell的showsReorderControl
属性设置成YES
,同时实现dataSource
中的tableView:moveRowAtIndexPath:toIndexPath:
方法。我们还可以同时通过实现dataSource
中的 tableView:canMoveRowAtIndexPath:
返回NO
,来禁用某一些cell的reordering功能。
上图中当tableView进入到edit模式的时候,tableView会去对当前可见的cell逐个调用
dataSource
的tableView:canMoveRowAtIndexPath:
方法(此处官方给出的流程图有点儿问题),决定当前cell是否显示reoedering控件,当开始进入拖动cell进行拖动的时候,每滑动过一个cell的时候,会去掉用delegate的tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:
方法,去判断当前划过的cell位置是否可以被替换,如果不行则给出建议的位置。当用户放手时本次reordering操作结束,调用dataSource中的tableView:moveRowAtIndexPath:toIndexPath:
方法更新tableView对应的数据。
IndexList
当我们tableView中section有很多,数据量比较大的时候我们可以引入indexList
,来方便完成section的定位,例如系统的通讯录程序。我们可以通过设置tableView的sectionIndexMinimumDisplayRowCount
属性来指定当tableView中多少行的时候开始显示IndexList
,默认的设置是NSIntegerMax
,即默认是不显示indexList的。
为了能够使用indexlist我们还需要实现dataSource中一下两个方法:
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView;
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index;
第一个方法返回用于显示在indexList中的内容的数组,通常为A,B,C...Z。第二个方法的主要作用是根据用户在indexList中点击的位置,返回相应的section的index值。这个例子可以在苹果官方给出的TableViewSuite中找到,实现起来还是很简单的。
网友评论