UITableView的數(shù)據(jù)源(dataSource)和代理(delegate)

UITableView的數(shù)據(jù)源(dataSource)和代理(delegate)

UITableView需要一個(gè)數(shù)據(jù)源(dataSource)來顯示數(shù)據(jù),UITableView會向數(shù)據(jù)源查詢一共有多少行數(shù)據(jù)以及每一行顯示什么數(shù)據(jù)等。沒有設(shè)置數(shù)據(jù)源的UITableView只是個(gè)空殼。凡是遵守UITableViewDataSource協(xié)議的OC對象,都可以是UITableView的數(shù)據(jù)源。

通常都要為UITableView設(shè)置代理對象(delegate),以便在UITableView觸發(fā)一下事件時(shí)做出相應(yīng)的處理,比如選中了某一行。凡是遵守了UITableViewDelegate協(xié)議的OC對象,都可以是UITableView的代理對象。一般會讓控制器充當(dāng)UITableView的dataSource和delegate

UITableViewDataSource

@required

-?(NSInteger)tableView:(UITableView?*)tableView?numberOfRowsInSection:(NSInteger)section;

第section分區(qū)一共有多少行

-?(UITableViewCell?*)tableView:(UITableView?*)tableViewcellForRowAtIndexPath:(NSIndexPath?*)indexPath;

創(chuàng)建第section分區(qū)第row行的UITableViewCell對象(indexPath包含了section和row)

@optional

-?(NSInteger)numberOfSectionsInTableView:(UITableView?*)tableView;

一共有多少個(gè)分區(qū)

-?(NSString?*)tableView:(UITableView?*)tableView?titleForHeaderInSection:(NSInteger)section;

第section分區(qū)的頭部標(biāo)題

-?(NSString?*)tableView:(UITableView?*)tableView?titleForFooterInSection:(NSInteger)section;

第section分區(qū)的底部標(biāo)題

-?(BOOL)tableView:(UITableView?*)tableView?canEditRowAtIndexPath:(NSIndexPath?*)indexPath;

某一行是否可以編輯(刪除)

-?(BOOL)tableView:(UITableView?*)tableView?canMoveRowAtIndexPath:(NSIndexPath?*)indexPath;

某一行是否可以移動來進(jìn)行重新排序

-?(NSArray?*)sectionIndexTitlesForTableView:(UITableView?*)tableView;

UITableView右邊的索引欄的內(nèi)容

-?(void)tableView:(UITableView?*)tableView?didSelectRowAtIndexPath:(NSIndexPath?*)indexPath

選中了UITableView的某一行

-?(CGFloat)tableView:(UITableView?*)tableView?heightForRowAtIndexPath:(NSIndexPath?*)indexPath

某一行的高度

-?(CGFloat)tableView:(UITableView?*)tableView?heightForHeaderInSection:(NSInteger)section

第section分區(qū)頭部的高度

-?(CGFloat)tableView:(UITableView?*)tableView?heightForFooterInSection:(NSInteger)section

第section分區(qū)尾部的高度

-?(UIView?*)tableView:(UITableView?*)tableView?viewForHeaderInSection:(NSInteger)section

第section分區(qū)頭部顯示的視圖

-?(UIView?*)tableView:(UITableView?*)tableView?viewForFooterInSection:(NSInteger)section

第section分區(qū)尾部顯示的視圖

-?(NSInteger)tableView:(UITableView?*)tableViewindentationLevelForRowAtIndexPath:(NSIndexPath?*)indexPath

設(shè)置每一行的等級縮進(jìn)(數(shù)字越小,等級越高)

UITableViewCell

UITableView的每一行都是一個(gè)UITableViewCell,通過dataSource的

tableView:cellForRowAtIndexPath:方法來初始化每一行

UITableViewCell是UIView的子類,內(nèi)部有個(gè)默認(rèn)的子視圖:contentView。contentView是UITableViewCell所顯示內(nèi)容的父視圖,并負(fù)責(zé)顯示一些輔助指示視圖。輔助指示視圖的作用是顯示一個(gè)表示動作的圖標(biāo),可以通過設(shè)置UITableViewCell的accessoryType來顯示,默認(rèn)是UITableViewCellAccessoryNone(不顯示輔助指示視圖),其他值如下:

UITableViewCellAccessoryDisclosureIndicator

UITableViewCellAccessoryDetailDisclosureButton

UITableViewCellAccessoryCheckmark

UITableViewCell的contentView

contentView下默認(rèn)有3個(gè)子視圖,其中的2個(gè)是UILabel(通過UITableViewCell的textLabel和detailTextLabel屬性訪問),第3個(gè)是UIImageView(通過UITableViewCell的imageView屬性訪問)

UITableViewCell還有一個(gè)UITableViewCellStyle屬性,用于決定使用contentView的哪些子視圖,以及這些子視圖在contentView中的位置

UITableViewCell對象的重用原理

iOS設(shè)備的內(nèi)存有限,如果用UITableView顯示成千上萬條數(shù)據(jù),就需要成千上萬個(gè)UITableViewCell對象的話,那將會耗盡iOS設(shè)備的內(nèi)存。要解決該問題,需要重用UITableViewCell對象

重用原理:當(dāng)滾動列表時(shí),部分UITableViewCell會移出窗口,UITableView會將窗口外的UITableViewCell放入一個(gè)對象池中,等待重用。當(dāng)UITableView要求dataSource返回UITableViewCell時(shí),dataSource會先查看這個(gè)對象池,如果池中有未使用的UITableViewCell,dataSource會用新的數(shù)據(jù)配置這個(gè)UITableViewCell,然后返回給UITableView,重新顯示到窗口中,從而避免創(chuàng)建新對象

還有一個(gè)非常重要的問題:有時(shí)候需要自定義UITableViewCell(用一個(gè)子類繼承UITableViewCell),而且每一行用的不一定是同一種UITableViewCell(如短信聊天布局),所以一個(gè)UITableView可能擁有不同類型的UITableViewCell,對象池中也會有很多不同類型的UITableViewCell,那么UITableView在重用UITableViewCell時(shí)可能會得到錯(cuò)誤類型的UITableViewCell

解決方案:UITableViewCell有個(gè)NSString?*reuseIdentifier屬性,可以在初始化UITableViewCell的時(shí)候傳入一個(gè)特定的字符串標(biāo)識來設(shè)置reuseIdentifier(一般用UITableViewCell的類名)。當(dāng)UITableView要求dataSource返回UITableViewCell時(shí),先通過一個(gè)字符串標(biāo)識到對象池中查找對應(yīng)類型的UITableViewCell對象,如果有,就重用,如果沒有,就傳入這個(gè)字符串標(biāo)識來初始化一個(gè)UITableViewCell對象

重用UITableViewCell對象

-?(UITableViewCell?*)tableView:(UITableView?*)tableViewcellForRowAtIndexPath:(NSIndexPath?*)indexPath

{

static?NSString?*identifier?=?@"UITableViewCell";

UITableViewCell?*cell?=?[tableView?dequeueReusableCellWithIdentifier:identifier];

if?(cell?==?nil)?{

cell?=?[[[UITableViewCell?alloc]?initWithStyle:UITableViewCellStyleDefault?reuseIdentifier:identifier]?autorelease];

}

cell.textLabel.text?=?[NSString?stringWithFormat:@"Text?%i",?indexPath.row];

return?cell;

}

UITableViewCell的常用屬性

設(shè)置背景

backgroundView

設(shè)置被選中時(shí)的背景視圖

selectedBackgroundView

selectionStyle屬性可設(shè)置UITableViewCell被選中時(shí)的背景顏色:

UITableViewCellSelectionStyleNone沒有顏色

UITableViewCellSelectionStyleBlue藍(lán)色(默認(rèn))

UITableViewCellSelectionStyleGray灰色

自定義UITableViewCell

一般有兩種方式:

用一個(gè)xib文件來描述UITableViewCell的內(nèi)容

通過代碼往UITableViewCell的contentView中添加子視圖,在初始化方法(比如init、initWithStyle:reuseIdentifier:)中添加子控件,在layoutSubviews方法中分配子控件的位置和大小

UITableView的編輯模式

UITableView有個(gè)editing屬性,設(shè)置為YES時(shí),可以進(jìn)入編輯模式。在編輯模式下,可以管理表格中的行,比如改變行的排列順序、增加行、刪除行,但不能修改行的內(nèi)容

多種方式開啟編輯模式

@property(nonatomic,getter=isEditing)?BOOL?editing

-?(void)setEditing:(BOOL)editing?animated:(BOOL)animated

刪除UITableView的行

首先要開啟編輯模式

實(shí)現(xiàn)UITableViewDataSource的如下方法:

-?(void)tableView:(UITableView?*)tableViewcommitEditingStyle:(UITableViewCellEditingStyle)editingStyle?forRowAtIndexPath:(NSIndexPath?*)indexPath

{

//如果UITableView提交的是刪除指令

if?(editingStyle?==?UITableViewCellEditingStyleDelete)?{

//刪除真實(shí)數(shù)據(jù)

//?[self.data?removeObjectAtIndex:indexPath.row];

//刪除UITableView中的某一行(帶動畫效果)

[tableView?deleteRowsAtIndexPaths:[NSArray?arrayWithObject:indexPath]?withRowAnimation:UITableViewRowAnimationLeft];

//如果不考慮動畫效果,也可以直接[tableView?reload];

}

}

移動UITableView的行

首先要開啟編輯模式

實(shí)現(xiàn)UITableViewDataSource的如下方法(如果沒有實(shí)現(xiàn)此方法,將無法換行)

-?(void)tableView:(UITableView?*)tableView?moveRowAtIndexPath:(NSIndexPath*)sourceIndexPath?toIndexPath:(NSIndexPath?*)destinationIndexPath

{

int?from?=?sourceIndexPath.row;

int?to?=?destinationIndexPath.row;

if?(from?==?to)?return;

//交換數(shù)據(jù)

//?[self.data?exchangeObjectAtIndex:from?withObjectAtIndex:to];

}

選中UITableView的行

當(dāng)某行被選中時(shí)會調(diào)用此方法(UITableViewDelegate的方法)

-?(void)tableView:(UITableView?*)tableView?didSelectRowAtIndexPath:(NSIndexPath*)indexPath

{

//取消選中某一行,讓被選中行的高亮顏色消失(帶動畫效果)

[tableView?deselectRowAtIndexPath:indexPath?animated:YES];

}

UITableView常用方法

-?(id)initWithFrame:(CGRect)frame?style:(UITableViewStyle)style

初始化一個(gè)UITableView,并且設(shè)置表格樣式

-?(void)reloadData重新訪問數(shù)據(jù)源,刷新界面

-?(NSInteger)numberOfSections分區(qū)的個(gè)數(shù)

-?(NSInteger)numberOfRowsInSection:(NSInteger)section

第section分區(qū)的行數(shù)

-?(UITableViewCell?*)cellForRowAtIndexPath:(NSIndexPath?*)indexPath

通過indexPath找到對應(yīng)的UITableViewCell對象

-?(void)setEditing:(BOOL)editing?animated:(BOOL)animated

是否要開啟編輯模式

-?(void)deselectRowAtIndexPath:(NSIndexPath?*)indexPath?animated:(BOOL)animated

取消選中某一行,讓被選中行的高亮顏色消失(帶動畫效果)

-?(id)dequeueReusableCellWithIdentifier:(NSString?*)identifier

通過identifier在(緩存)池中找到對應(yīng)的UITableViewCell對象

-?(void)deleteRowsAtIndexPaths:(NSArray?*)indexPathswithRowAnimation:(UITableViewRowAnimation)animation

移除indexPaths范圍內(nèi)的所有行

@property(nonatomic,readonly)?UITableViewStyle?style表格樣式

@property(nonatomic,assign)?id??dataSource

數(shù)據(jù)源

@property(nonatomic,assign)?id??delegate代理

@property(nonatomic,getter=isEditing)?BOOL?editing是否為編輯模式

@property(nonatomic)?UITableViewCellSeparatorStyle?separatorStyle

設(shè)置分隔線的樣式

@property(nonatomic,retain)?UIColor?*separatorColor

設(shè)置分隔線的顏色

@property(nonatomic,retain)?UIView?*tableHeaderView

表頭顯示的視圖

@property(nonatomic,retain)?UIView?*tableFooterView

表尾顯示的視圖

@property(nonatomic)?BOOL?allowsSelection

是否允許選中行

@property(nonatomic)?BOOL?allowsSelectionDuringEditing

是否允許在編輯模式下選中行

@property(nonatomic)?BOOL?allowsMultipleSelection

是否允許選中多行

@property(nonatomic)?BOOL?allowsMultipleSelectionDuringEditing

是否允許在編輯模式下選中多行

UITableViewController

是UIViewController的子類,UITableViewController默認(rèn)扮演了3種角色:視圖控制器、UITableView的數(shù)據(jù)源和代理

UITableViewController的view是個(gè)UITablView,由UITableViewController負(fù)責(zé)設(shè)置和顯示這個(gè)對象。UITableViewController對象被創(chuàng)建后,會將這個(gè)UITableView對象的dataSource和delegate指向UITableViewController自己

一、UITableView

1.數(shù)據(jù)展示的條件

1>?UITableView的所有數(shù)據(jù)都是由數(shù)據(jù)源(dataSource)提供的,所以要想在UITableView展示數(shù)據(jù),必須設(shè)置UITableView的dataSource數(shù)據(jù)源對象

2>要想當(dāng)UITableView的dataSource對象,必須遵守UITableViewDataSource協(xié)議,實(shí)現(xiàn)相應(yīng)的數(shù)據(jù)源方法

3>當(dāng)UITableView想要展示數(shù)據(jù)的時(shí)候,就會給數(shù)據(jù)源發(fā)送消息(調(diào)用數(shù)據(jù)源方法),UITableView會根據(jù)方法返回值決定展示怎樣的數(shù)據(jù)

2.數(shù)據(jù)展示的過程

1>先調(diào)用數(shù)據(jù)源的

-?(NSInteger)numberOfSectionsInTableView:(UITableView?*)tableView

得知一共有多少組

2>然后調(diào)用數(shù)據(jù)源的

-?(NSInteger)tableView:(UITableView?*)tableView?numberOfRowsInSection:(NSInteger)section

得知第section組一共有多少行

3>然后調(diào)用數(shù)據(jù)源的

-?(UITableViewCell?*)tableView:(UITableView?*)tableView?cellForRowAtIndexPath:(NSIndexPath?*)indexPath

得知第indexPath.section組?第indexPath.row行顯示怎樣的cell(顯示什么內(nèi)容)

3.常見數(shù)據(jù)源方法

1>一共有多少組

-?(NSInteger)numberOfSectionsInTableView:(UITableView?*)tableView

2>第section組一共有多少行

-?(NSInteger)tableView:(UITableView?*)tableView?numberOfRowsInSection:(NSInteger)section

3>第indexPath.section組?第indexPath.row行顯示怎樣的cell(顯示什么內(nèi)容)

-?(UITableViewCell?*)tableView:(UITableView?*)tableView?cellForRowAtIndexPath:(NSIndexPath?*)indexPath

4>第section組顯示怎樣的頭部標(biāo)題

-?(NSString?*)tableView:(UITableView?*)tableView?titleForHeaderInSection:(NSInteger)section;

5>第section組顯示怎樣的尾部標(biāo)題

-?(NSString?*)tableView:(UITableView?*)tableView?titleForFooterInSection:(NSInteger)section;

4.tableView刷新數(shù)據(jù)的方式

1>修改模型數(shù)據(jù)

2>刷新表格

*?reloadData整體刷新(每一行都會刷新)

*?-?(void)reloadRowsAtIndexPaths:(NSArray?*)indexPathswithRowAnimation:(UITableViewRowAnimation)animation

局部刷新

5.性能優(yōu)化

1>定義一個(gè)循環(huán)利用標(biāo)識

static?NSString?*ID?=?@"C1";

2>從緩存池中取出可循環(huán)利用的cell

UITableViewCell?*cell?=?[tableView?dequeueReusableCellWithIdentifier:ID];

3>如果緩存池中沒有可循環(huán)利用的cell

if?(cell?==?nil)

{

cell?=?[[UITableViewCell?alloc]?initWithStyle:UITableViewCellStyleDefault?reuseIdentifier:ID];

}

4>覆蓋cell上面的數(shù)據(jù)

cell.textLabel.text?=?[NSString?stringWithFormat:@"第%d行數(shù)據(jù)",?indexPath.row];

1.UITableView繼承UIScrollView.

2.實(shí)例一城市列表思路:

步驟一:創(chuàng)建UITableView。UITableView樣式為組

步驟二:設(shè)置UITableView的數(shù)據(jù)源方法。

步驟三:實(shí)現(xiàn)UITableView的數(shù)據(jù)源方法,此方法會自動調(diào)用。

返回有多少組

返回一組有多少行

返回每一行顯示的UITableViewCell(繼承UIView),initWithStyle使用這個(gè)方法調(diào)用。

注意UITableView的數(shù)據(jù)源的方法普遍都是以tableView開頭。

步驟四:用數(shù)組管理數(shù)據(jù)。

步驟五:每個(gè)數(shù)組中都是一個(gè)字典,key:(header,footer,cityes).

3.擴(kuò)展性好:指的是需求改了,代碼不需要怎么改。

4.創(chuàng)建模型的時(shí)候,自定義一個(gè)工廠方法(類方法)接口給外界調(diào)用。

工廠方法好處:簡化對象的實(shí)例化,快速創(chuàng)建對象。

5.UITableViewCell

UITableViewCellStyleDefault

UITableViewCellStyleValue1

UITableViewCellStyleSubtitle

UITableViewCellStyleValue2

6.UITableViewCell設(shè)置右邊輔助視圖accessoryType;

UITableViewCellAccessoryDisclosureIndicator

UITableViewCellAccessoryDetailDisclosureButton

UITableViewCellAccessoryCheckmark

7.快捷創(chuàng)建代碼方法中<#???#>用法。

8.中文字前面不要加\,會把\后面的中文轉(zhuǎn)義,正確描述:圖書/音像

9.UIAlertView

UIAlertView?*alert?=?[[UIAlertView?alloc]?initWithTitle:@"產(chǎn)品信息展示"?message:@"哈哈哈哈哈"?delegate:nil?cancelButtonTitle:@"ABC"?otherButtonTitles:@"123",@"456",?nil];

//?彈出UIAlertView

[alert?show];

UIAlertView?*alert?=?[[UIAlertView?alloc]?initWithTitle:@"產(chǎn)品信息展示"?message:@"哈哈哈哈哈"?delegate:nil?cancelButtonTitle:@"取消"?otherButtonTitles:@"確定",?nil];

//?彈出UIAlertView

[alert?show];

UIAlertView?*alert?=?[[UIAlertView?alloc]?initWithTitle:@"產(chǎn)品信息展示"?message:p.name?delegate:nil?cancelButtonTitle:@"取消"?otherButtonTitles:@"確定",?nil];

alert.alertViewStyle?=?UIAlertViewStyleLoginAndPasswordInput;

//?彈出UIAlertView

[alert?show];

UIAlertView?*alert?=?[[UIAlertView?alloc]?initWithTitle:@"產(chǎn)品信息展示"?message:p.name?delegate:nil?cancelButtonTitle:@"取消"?otherButtonTitles:@"確定",?nil];

alert.alertViewStyle?=?UIAlertViewStylePlainTextInput;

//?彈出UIAlertView

[alert?show];

UIAlertView?*alert?=?[[UIAlertView?alloc]?initWithTitle:@"產(chǎn)品信息展示"?message:p.name?delegate:nil?cancelButtonTitle:@"取消"?otherButtonTitles:@"確定",?nil];

alert.alertViewStyle?=?UIAlertViewStyleSecureTextInput;

//?彈出UIAlertView

[alert?show];

10.監(jiān)聽UIAlertView的事件.

步驟一:設(shè)置UIAlertView的代理

步驟二:遵守UIAlertView的協(xié)議

步驟三:實(shí)現(xiàn)UIAlertView的按鈕點(diǎn)擊協(xié)議方法。

11.按鈕方法內(nèi)部實(shí)現(xiàn)

步驟一:?取出文本框文字

注意UIAlertView中的文本框的角標(biāo)是根據(jù)UIAlertView從上到下第幾個(gè)文本框決定的。最上面的文本框角標(biāo)為0.

步驟二:修改模型數(shù)據(jù)

步驟三:刷新表格

12.UITableView中的reloadData,會重新整個(gè)表格。

13.-(void)reloadRowsAtIndexPaths:(NSArray*)indexPaths?withRowAnimation:(UITableViewRowAnimation)animation

//指定刷新indexPaths數(shù)組里的行數(shù)。

注意indexPaths里存儲的是NSIndexPath對象

14.UITableView的性能優(yōu)化

UITableView默認(rèn)只會加載出現(xiàn)在屏幕上面的cell,沒當(dāng)有一個(gè)cell移除屏幕,就會存儲到緩存池里找。

性能優(yōu)化步驟:

步驟一:定義cell的標(biāo)識(不需要每次都創(chuàng)建cell標(biāo)識,因此需要使用static,static標(biāo)識只會在第一次創(chuàng)建,以后都不會創(chuàng)建了。)

步驟二:從緩存池里取cell

步驟三:判斷取出cell是否為空,如果為空就手動創(chuàng)建cell。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容