一、簡(jiǎn)介
-
官方給出了比較全面的介紹,要點(diǎn)摘錄如下:
table view的作用:導(dǎo)航、展示索引列表、展示詳情信息、展示選項(xiàng)列表
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中,相當(dāng)于一個(gè)二維數(shù)組,用indexPath.section和indexPath.row索引
- table view有自己的header和footer,每個(gè)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分類(lèi)和數(shù)據(jù)源:plain和grouped,通過(guò)data source代理渲染內(nèi)容,使用的source是 UITableViewCell,對(duì)于cell應(yīng)該了解如下幾點(diǎn)
- cells可以展示text,image等內(nèi)容
- 在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, 也可以自己設(shè)置accessory view



table view的代理方法
- intermediate level:展示一個(gè)新的tableview
- leaf node:展示選中項(xiàng)的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在一般模式和編輯模式下的機(jī)構(gòu)圖


-
cell style
cell styles是在UITableViewCell.h中聲明的結(jié)構(gòu)體:
typedef enum {
UITableViewCellStyleDefault,
UITableViewCellStyleValue1,
UITableViewCellStyleValue2,
UITableViewCellStyleSubtitle
} UITableViewCellStyle;
cell對(duì)象有兩種內(nèi)容分別為text和image,結(jié)構(gòu)圖如下所示

-
table view cell的屬性和用法
cell content由下面UITableViewCell的三個(gè)屬性確定
- textLabel: 主標(biāo)題
- detailTextLabel:副標(biāo)題
- 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;
}
對(duì)cell可以設(shè)置如下屬性:
-
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
四種預(yù)設(shè)風(fēng)格的cell已經(jīng)可以解決大部分問(wèn)題了。每row都可以添加1到2種label,可以選擇性的添加image和accessory view,這些添加對(duì)象的屬性都可以背修改,另外it can supply an image for the row in its selected state as well as its normal state.
雖然如此,這仍不能滿(mǎn)足我們所有的需求,預(yù)定風(fēng)格cell的內(nèi)容(content)都有固定的位置,有時(shí)候我們需要在Cell中添加不同的元素,并且這些元素的位置也有各自要求。這時(shí)不能使用預(yù)定的cell,我們有兩個(gè)辦法:
- Add subviews to a cell’s content view.
- Create a custom subclass of UITableViewCell.
-
UITableView的cell重用標(biāo)識(shí)
UITableView中的單元格cell是在顯示到用戶(hù)可視區(qū)域后創(chuàng)建的,那么如果用戶(hù)往下滾動(dòng)就會(huì)繼續(xù)創(chuàng)建顯示在屏幕上的單元格,如果用戶(hù)向上滾動(dòng)返回到查看過(guò)的內(nèi)容時(shí)同樣會(huì)重新創(chuàng)建之前已經(jīng)創(chuàng)建過(guò)的單元格。如此一來(lái)即使UITableView的內(nèi)容不是太多,如果用戶(hù)反復(fù)的上下滾動(dòng),內(nèi)存也會(huì)瞬間飆升,更何況很多時(shí)候UITableView的內(nèi)容是很多的(例如微博展示列表,基本向下滾動(dòng)是沒(méi)有底限的)。
重用已經(jīng)不再界面顯示的已創(chuàng)建過(guò)的Cell可以解決這個(gè)問(wèn)題。UITableView已經(jīng)為我們實(shí)現(xiàn)了這種機(jī)制。在UITableView內(nèi)部有一個(gè)緩存池,初始化時(shí)使用initWithStyle:(UITableViewCellStyle) reuseIdentifier:(NSString *)方法指定一個(gè)可重用標(biāo)識(shí),就可以將這個(gè)cell放到緩存池。然后在使用時(shí)使用指定的標(biāo)識(shí)去緩存池中取得對(duì)應(yīng)的cell然后修改cell內(nèi)容即可。可重用標(biāo)識(shí)可以有多個(gè),如果在UITableView中有多類(lèi)結(jié)構(gòu)不同的Cell,可以通過(guò)這個(gè)標(biāo)識(shí)進(jìn)行緩存和重新。下面用這行代碼解釋一下:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
#NSIndexPath是一個(gè)對(duì)象,記錄了組和行信息
#由于此方法調(diào)用十分頻繁,cell的標(biāo)示聲明成靜態(tài)變量有利于性能優(yōu)化
static NSString *cellIdentifier=@"UITableViewCellIdentifierKey1";
#首先根據(jù)標(biāo)識(shí)去緩存池取
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
#如果緩存池沒(méi)有到則重新創(chuàng)建并放到緩存池中
if(!cell){
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier];
}
return cell;
}
關(guān)于標(biāo)識(shí)符重用問(wèn)題下面附一篇講解比較細(xì)致的博文
下文摘自iOS UITableView的cell重用標(biāo)識(shí)
UITableView繼承自UIScrollview,是蘋(píng)果為我們封裝好的一個(gè)基于scroll的控件。上面主要是一個(gè)個(gè)的 UITableViewCell,可以讓UITableViewCell響應(yīng)一些點(diǎn)擊事件,也可以在UITableViewCell中加入 UITextField或者UITextView等子視圖,使得可以在cell上進(jìn)行文字編輯。
UITableView中的cell可以有很多,一般會(huì)通過(guò)重用cell來(lái)達(dá)到節(jié)省內(nèi)存的目的:通過(guò)為每個(gè)cell指定一個(gè)重用標(biāo)識(shí)符 (reuseIdentifier),即指定了單元格的種類(lèi),當(dāng)cell滾出屏幕時(shí),會(huì)將滾出屏幕的單元格放入重用的queue中,當(dāng)某個(gè)未在屏幕上的單 元格要顯示的時(shí)候,就從這個(gè)queue中取出單元格進(jìn)行重用。
但對(duì)于多變的自定義cell,有時(shí)這種重用機(jī)制會(huì)出錯(cuò)。比如,當(dāng)一個(gè)cell含有一個(gè)UITextField的子類(lèi)并被放在重用queue中以待重用,這 時(shí)如果一個(gè)未包含任何子視圖的cell要顯示在屏幕上,就會(huì)取出并使用這個(gè)重用的cell顯示在無(wú)任何子視圖的cell中,這時(shí)候就會(huì)出錯(cuò)。
解決方法:
方法1 將獲得cell的方法從- (UITableViewCell)dequeueReusableCellWithIdentifier: (NSString)identifier 換為-(UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath
重用機(jī)制調(diào)用的就是dequeueReusableCellWithIdentifier這個(gè)方法,方法的意思就是“出列可重用的cell”,因而只要將 它換為cellForRowAtIndexPath(只從要更新的cell的那一行取出cell),就可以不使用重用機(jī)制,因而問(wèn)題就可以得到解決,雖然 可能會(huì)浪費(fèi)一些空間。
示例代碼:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; //改為以下的方法
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; //根據(jù)indexPath準(zhǔn)確地取出一行,而不是從cell重用隊(duì)列中取出
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準(zhǔn)確地取出一行,而不是從cell重用隊(duì)列中取出
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
}
方法2 通過(guò)為每個(gè)cell指定不同的重用標(biāo)識(shí)符(reuseIdentifier)來(lái)解決。
重用機(jī)制是根據(jù)相同的標(biāo)識(shí)符來(lái)重用cell的,標(biāo)識(shí)符不同的cell不能彼此重用。于是我們將每個(gè)cell的標(biāo)識(shí)符都設(shè)置為不同,就可以避免不同cell重用的問(wèn)題了。
示例代碼:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%d%d", [indexPath section], [indexPath row]];//以indexPath來(lái)唯一確定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來(lái)唯一確定cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; //出列可重用的cell
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
}
方法3 刪除重用cell的所有子視圖,這個(gè)方法是通過(guò)刪除重用的cell的所有子視圖,從而得到一個(gè)沒(méi)有特殊格式的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];
}
}
}
文章結(jié)束
三、常用操作
UITableView和UITableViewCell提供了強(qiáng)大的操作功能,這一節(jié)中會(huì)重點(diǎn)討論刪除、增加、排序等操作
1
1
1
11
1
1