一、简介
-
官方给出了比较全面的介绍,要点摘录如下:
table view的作用:导航、展示索引列表、展示详情信息、展示选项列表
Table views are versatile user interface objects frequently found in iOS apps. A table view presents data in a scrollable list of multiple rows that may be divided into sections.Table views have many purposes:
- To let users navigate through hierarchically structured data
- To present an indexed list of items
- To display detail information and controls in visually distinct groupings
- To present a selectable list of options
table view的组成:
- 一列多行的纵向scrollView
- 分为section和row,row在section中,相当于一个二维数组,用indexPath.section和indexPath.row索引
- table view有自己的header和footer,每个section也有自己的header和footer
A table view has only one column and allows vertical scrolling only. It consists of rows in sections. Each section can have a header and a footer that displays text or an image. However, many table views have only one section with no visible header or footer. Programmatically, the UIKit framework identifies rows and sections through their index number: Sections are numbered 0 through n – 1 from the top of a table view to the bottom; rows are numbered 0 through n – 1 within a section. A table view can have its own header and footer, distinct from any section; the table header appears before the first row of the first section, and the table footer appears after the last row of the last section.
table view的style分类和数据源:plain和grouped,通过data source代理渲染内容,使用的source是 UITableViewCell,对于cell应该了解如下几点
- cells可以展示text,image等内容
- 在normal和selected状态可以有背景view
- 还可以有accessory view作为控制方法
A table view is an instance of the UITableView class in one of two basic styles, plain or grouped. A plain table view is an unbroken list; a grouped table view has visually distinct sections. A table view has a data source and might have a delegate. The data source object provides the data for populating the sections and rows of the table view. The delegate object customizes its appearance and behavior.
A table view draws its visible rows using cells—that is, UITableViewCell objects. Cells are views that can display text, images, or other kinds of content. They can have background views for both normal and selected states. Cells can also have accessory views, which function as controls for selecting or setting an option.
下面是四种cellstyle
下面是三种accessory view, 也可以自己设置accessory view
table view的代理方法
- intermediate level:展示一个新的tableview
- leaf node:展示选中项的details
When users select a row (by tapping it), the delegate of the table view is informed via a message. The delegate is passed the indexes of the row and the section that the row is in. It uses this information to locate the corresponding item in the app’s data model. This item might be at an intermediate level in the hierarchy of data or it might be a “leaf node" in the hierarchy. If the item is at an intermediate level, the app displays a new table view. If the item is a leaf node, the app displays details about the selected item in a grouped-style table view or some other kind of view.In table views that list a series of options, tapping a row simply selects its associated option. No subsequent view of data is displayed.
table view的编辑模式:可以insert, delete或者relocate rows
Table views can enter an editing mode in which users can insert or delete rows, or relocate them within the table. In editing mode, rows that are marked for insertion or deletion display a green plus sign (insertion) or a red minus sign (deletion) near the left edge of the row. If users touch a deletion control or, in some table views, swipe across a row, a red Delete button appears, prompting users to delete that row. Rows that can be relocated display (near their right edge) an image consisting of several horizontal lines. When the table view leaves editing mode, the insertion, deletion, and reordering controls disappear.
When users attempt to insert, delete, or reorder rows, the table view sends a sequence of messages to its data source and delegate so that they can manage these operations.
-
参考链接
- View Controller Programming Guide for iOS
- Table View Styles and Accessory Views
- iOS Human Interface Guidelines
- Table View Animations and Gestures
二、table view cell解析
-
table view cell在一般模式和编辑模式下的机构图
-
cell style
cell styles是在UITableViewCell.h中声明的结构体:
typedef enum {
UITableViewCellStyleDefault,
UITableViewCellStyleValue1,
UITableViewCellStyleValue2,
UITableViewCellStyleSubtitle
} UITableViewCellStyle;
cell对象有两种内容分别为text和image,结构图如下所示
-
table view cell的属性和用法
cell content由下面UITableViewCell的三个属性确定
- textLabel: 主标题
- detailTextLabel:副标题
- imageView :前部图片
下面给出一段使用UITableViewCell的代码示例
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"MyIdentifier"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
NSDictionary *item = (NSDictionary *)[self.content objectAtIndex:indexPath.row];
cell.textLabel.text = [item objectForKey:@"mainTitleKey"];
cell.detailTextLabel.text = [item objectForKey:@"secondaryTitleKey"];
NSString *path = [[NSBundle mainBundle] pathForResource:[item objectForKey:@"imageKey"] ofType:@"png"];
UIImage *theImage = [UIImage imageWithContentsOfFile:path];
cell.imageView.image = theImage;
return cell;
}
对cell可以设置如下属性:
-
selectionStyle
— Controls the appearance of the cell when selected. -
accessoryType
andaccessoryView
— Allow you to set one of the standard accessory views (disclosure indicator or detail disclosure control) or a custom accessory view for a cell in normal (nonediting) mode. For a custom view, you may provide any UIView object, such as a slider, a switch, or a custom view -
editingAccessoryType
andeditingAccessoryView
— Allow you to set one of the standard accessory views (disclosure indicator or detail disclosure control) or a custom accessory view for a cell in editing mode. For a custom view, you may provide any UIView object, such as a slider, a switch, or a custom view. -
showsReorderControl
— Specifies whether it shows a reordering control when in editing mode. The related but read-only editingStyle property specifies the type of editing control the cell has (if any). The delegate returns the value of the editingStyle property in its implementation of the tableView:editingStyleForRowAtIndexPath: method. -
backgroundView
andselectedBackgroundView
— Provide a background view (when a cell is unselected and selected) to display behind all other views of the cell. -
indentationLevel
andindentationWidth
— Specify the indentation level for cell content and the width of each indentation level.
-
自定义Cell
四种预设风格的cell已经可以解决大部分问题了。每row都可以添加1到2种label,可以选择性的添加image和accessory view,这些添加对象的属性都可以背修改,另外it can supply an image for the row in its selected state as well as its normal state.
虽然如此,这仍不能满足我们所有的需求,预定风格cell的内容(content)都有固定的位置,有时候我们需要在Cell中添加不同的元素,并且这些元素的位置也有各自要求。这时不能使用预定的cell,我们有两个办法:
- Add subviews to a cell’s content view.
- Create a custom subclass of UITableViewCell.
-
UITableView的cell重用标识
UITableView中的单元格cell是在显示到用户可视区域后创建的,那么如果用户往下滚动就会继续创建显示在屏幕上的单元格,如果用户向上滚动返回到查看过的内容时同样会重新创建之前已经创建过的单元格。如此一来即使UITableView的内容不是太多,如果用户反复的上下滚动,内存也会瞬间飙升,更何况很多时候UITableView的内容是很多的(例如微博展示列表,基本向下滚动是没有底限的)。
重用已经不再界面显示的已创建过的Cell可以解决这个问题。UITableView已经为我们实现了这种机制。在UITableView内部有一个缓存池,初始化时使用initWithStyle:(UITableViewCellStyle) reuseIdentifier:(NSString *)方法指定一个可重用标识,就可以将这个cell放到缓存池。然后在使用时使用指定的标识去缓存池中取得对应的cell然后修改cell内容即可。可重用标识可以有多个,如果在UITableView中有多类结构不同的Cell,可以通过这个标识进行缓存和重新。下面用这行代码解释一下:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
#NSIndexPath是一个对象,记录了组和行信息
#由于此方法调用十分频繁,cell的标示声明成静态变量有利于性能优化
static NSString *cellIdentifier=@"UITableViewCellIdentifierKey1";
#首先根据标识去缓存池取
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
#如果缓存池没有到则重新创建并放到缓存池中
if(!cell){
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier];
}
return cell;
}
关于标识符重用问题下面附一篇讲解比较细致的博文
UITableView继承自UIScrollview,是苹果为我们封装好的一个基于scroll的控件。上面主要是一个个的 UITableViewCell,可以让UITableViewCell响应一些点击事件,也可以在UITableViewCell中加入 UITextField或者UITextView等子视图,使得可以在cell上进行文字编辑。
UITableView中的cell可以有很多,一般会通过重用cell来达到节省内存的目的:通过为每个cell指定一个重用标识符 (reuseIdentifier),即指定了单元格的种类,当cell滚出屏幕时,会将滚出屏幕的单元格放入重用的queue中,当某个未在屏幕上的单 元格要显示的时候,就从这个queue中取出单元格进行重用。
但对于多变的自定义cell,有时这种重用机制会出错。比如,当一个cell含有一个UITextField的子类并被放在重用queue中以待重用,这 时如果一个未包含任何子视图的cell要显示在屏幕上,就会取出并使用这个重用的cell显示在无任何子视图的cell中,这时候就会出错。
解决方法:
方法1 将获得cell的方法从- (UITableViewCell)dequeueReusableCellWithIdentifier: (NSString)identifier 换为-(UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath
重用机制调用的就是dequeueReusableCellWithIdentifier这个方法,方法的意思就是“出列可重用的cell”,因而只要将 它换为cellForRowAtIndexPath(只从要更新的cell的那一行取出cell),就可以不使用重用机制,因而问题就可以得到解决,虽然 可能会浪费一些空间。
示例代码:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; //改为以下的方法
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; //根据indexPath准确地取出一行,而不是从cell重用队列中取出
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
//...其他代码
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; //改为以下的方法
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; //根据indexPath准确地取出一行,而不是从cell重用队列中取出
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
}
方法2 通过为每个cell指定不同的重用标识符(reuseIdentifier)来解决。
重用机制是根据相同的标识符来重用cell的,标识符不同的cell不能彼此重用。于是我们将每个cell的标识符都设置为不同,就可以避免不同cell重用的问题了。
示例代码:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%d%d", [indexPath section], [indexPath row]];//以indexPath来唯一确定cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; //出列可重用的cell
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%d%d", [indexPath section], [indexPath row]];//以indexPath来唯一确定cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; //出列可重用的cell
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
}
方法3 删除重用cell的所有子视图,这个方法是通过删除重用的cell的所有子视图,从而得到一个没有特殊格式的cell,供其他cell重用。
示例代码:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; //出列可重用的cell
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
else
{
//删除cell的所有子视图
while ([cell.contentView.subviews lastObject] != nil)
{
[(UIView)[cell.contentView.subviews lastObject] removeFromSuperview];
}
}
}
文章结束
三、常用操作
UITableView和UITableViewCell提供了强大的操作功能,这一节中会重点讨论删除、增加、排序等操作
1
1
1
11
1
1