UIKit (4)----萬能的UITableView

一、簡介

  1. 官方給出了比較全面的介紹,要點摘錄如下:

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.

幾種tableview
幾種tableview

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

default: 主標題和可選的image
default: 主標題和可選的image

subtitle: 左對齊主標題、下面灰色副標題和可選擇image
subtitle: 左對齊主標題、下面灰色副標題和可選擇image

value1: 左對齊的主標題和右對齊的藍色副標題,不允許image,通常用來做setting頁面
value1: 左對齊的主標題和右對齊的藍色副標題,不允許image,通常用來做setting頁面

value2: 藍色主標題和黑色副標題,用于解釋頁面,比如聯(lián)系人頁面
value2: 藍色主標題和黑色副標題,用于解釋頁面,比如聯(lián)系人頁面

下面是三種accessory view, 也可以自己設置accessory view

UITableViewCellAccessoryDisclosureIndicator
UITableViewCellAccessoryDisclosureIndicator

UITableViewCellAccessoryDetailDisclosureButton
UITableViewCellAccessoryDetailDisclosureButton

UITableViewCellAccessoryCheckmark
UITableViewCellAccessoryCheckmark

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.

  1. 參考鏈接

二、table view cell解析

  1. table view cell在一般模式和編輯模式下的機構圖

Parts of a table view cell
Parts of a table view cell

Parts of a table-view cell in editing mode
Parts of a table-view cell in editing mode
  1. cell style

cell styles是在UITableViewCell.h中聲明的結構體:
typedef enum {
UITableViewCellStyleDefault,
UITableViewCellStyleValue1,
UITableViewCellStyleValue2,
UITableViewCellStyleSubtitle
} UITableViewCellStyle;

cell對象有兩種內容分別為text和image,結構圖如下所示

Default cell content in a UITableViewCell object
Default cell content in a UITableViewCell object
  1. 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 and accessoryView — 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 and editingAccessoryView — 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 and selectedBackgroundView — Provide a background view (when a cell is unselected and selected) to display behind all other views of the cell.
  • indentationLevel and indentationWidth — Specify the indentation level for cell content and the width of each indentation level.
  1. 自定義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.
  1. 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;
    }

關于標識符重用問題下面附一篇講解比較細致的博文

下文摘自iOS UITableView的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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379

推薦閱讀更多精彩內容

  • 概述在iOS開發(fā)中UITableView可以說是使用最廣泛的控件,我們平時使用的軟件中到處都可以看到它的影子,類似...
    liudhkk閱讀 9,084評論 3 38
  • //設置行高 (CGFloat)tableView:(UITableView *)tableView height...
    俊月閱讀 1,309評論 0 1
  • 好文章,轉載一下,有機會好好研究下 今天在研究SDWebImage和ASIHTTPRequest實現(xiàn)網(wǎng)絡圖片異步加...
    Apollo2016閱讀 2,001評論 0 2
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結起來就是把...
    Dove_iOS閱讀 27,198評論 30 471
  • 我最愛的果果和卷卷: 昨天還是奶奶我們仨守在家里,平常總覺得五個人擁擠的小窩,這十天以來,一天比一天空曠冷清。我和...
    雨后木樨閱讀 191評論 0 0