一、簡介
-
官方給出了比較全面的介紹,要點摘錄如下:
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中,相當于一個二維數(shù)組,用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分類和數(shù)據(jù)源:plain和grouped,通過data source代理渲染內容,使用的source是 UITableViewCell,對于cell應該了解如下幾點
- cells可以展示text,image等內容
- 在normal和selected狀態(tài)可以有背景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 “l(fā)eaf 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已經(jīng)可以解決大部分問題了。每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是在顯示到用戶可視區(qū)域后創(chuàng)建的,那么如果用戶往下滾動就會繼續(xù)創(chuàng)建顯示在屏幕上的單元格,如果用戶向上滾動返回到查看過的內容時同樣會重新創(chuàng)建之前已經(jīng)創(chuàng)建過的單元格。如此一來即使UITableView的內容不是太多,如果用戶反復的上下滾動,內存也會瞬間飆升,更何況很多時候UITableView的內容是很多的(例如微博展示列表,基本向下滾動是沒有底限的)。
重用已經(jīng)不再界面顯示的已創(chuàng)建過的Cell可以解決這個問題。UITableView已經(jīng)為我們實現(xiàn)了這種機制。在UITableView內部有一個緩存池,初始化時使用initWithStyle:(UITableViewCellStyle) reuseIdentifier:(NSString *)方法指定一個可重用標識,就可以將這個cell放到緩存池。然后在使用時使用指定的標識去緩存池中取得對應的cell然后修改cell內容即可。可重用標識可以有多個,如果在UITableView中有多類結構不同的Cell,可以通過這個標識進行緩存和重新。下面用這行代碼解釋一下:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
#NSIndexPath是一個對象,記錄了組和行信息
#由于此方法調用十分頻繁,cell的標示聲明成靜態(tài)變量有利于性能優(yōu)化
static NSString *cellIdentifier=@"UITableViewCellIdentifierKey1";
#首先根據(jù)標識去緩存池取
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
#如果緩存池沒有到則重新創(chuàng)建并放到緩存池中
if(!cell){
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier];
}
return cell;
}
關于標識符重用問題下面附一篇講解比較細致的博文
UITableView繼承自UIScrollview,是蘋果為我們封裝好的一個基于scroll的控件。上面主要是一個個的 UITableViewCell,可以讓UITableViewCell響應一些點擊事件,也可以在UITableViewCell中加入 UITextField或者UITextView等子視圖,使得可以在cell上進行文字編輯。
UITableView中的cell可以有很多,一般會通過重用cell來達到節(jié)省內存的目的:通過為每個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]; //根據(jù)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]; //根據(jù)indexPath準確地取出一行,而不是從cell重用隊列中取出
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
}
方法2 通過為每個cell指定不同的重用標識符(reuseIdentifier)來解決。
重用機制是根據(jù)相同的標識符來重用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提供了強大的操作功能,這一節(jié)中會重點討論刪除、增加、排序等操作
1
1
1
11
1
1