一镀首、UITableView基本介紹
默認(rèn)的UITableView有2種風(fēng)格:
UITableViewStylePlain(不分組)
UITableViewStyleGrouped(分組)
UITableView
中的數(shù)據(jù)只有行的概念,沒有列的概念,UITableView的每行數(shù)據(jù)就是一個(gè)UITableViewCell
廊宪。
自帶的UITableViewCell
的類型選擇有:
typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
UITableViewCellStyleDefault, // 左側(cè)顯示textLabel(不顯示detailTextLabel)脚草,imageView可選(顯示在最左邊)
UITableViewCellStyleValue1, // 左側(cè)顯示textLabel乓序、右側(cè)顯示detailTextLabel(默認(rèn)藍(lán)色)批狱,imageView可選(顯示在最左邊)
UITableViewCellStyleValue2, // 左側(cè)依次顯示textLabel(默認(rèn)藍(lán)色)和detailTextLabel,imageView可選(顯示在最左邊)
UITableViewCellStyleSubtitle // 左上方顯示textLabel梅尤,左下方顯示detailTextLabel(默認(rèn)灰色),imageView可選(顯示在最左邊)
};
二柜思、UITableViewDataSource數(shù)據(jù)源
數(shù)據(jù)源的作用就是告訴UITableView
,我該顯示什么數(shù)據(jù)
#pragma mark 常用數(shù)據(jù)源方法
#pragma mark 返回分組數(shù)
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
#pragma mark 返回每組行數(shù)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
#pragma mark 返回每行的單元格
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
#pragma mark 返回每組頭標(biāo)題名稱
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
#pragma mark 返回每組尾部說明
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
計(jì)算分組數(shù) -> 計(jì)算每組行數(shù) -> 生成分組索引 -> 生成單元格
注意:cellForRowAtIndexPath只生產(chǎn)當(dāng)前顯示在界面上的單元格
三巷燥、UITableViewDelegate代理
代理的作用是告訴UITableView
赡盘,我該怎么顯示和響應(yīng)
#pragma mark - 常用代理方法
#pragma mark 設(shè)置分組頭部的內(nèi)容高度
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
#pragma mark 設(shè)置每行高度(每行高度可以不一樣)
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
#pragma mark 設(shè)置分組尾部的內(nèi)容高度
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
#pragma mark 點(diǎn)擊了某一行
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
#pragma mark 設(shè)置分組的頭部視圖
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
#pragma mark 設(shè)置分組的尾部視圖
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;
四、UITableView刷新列表方法
#pragma mark 刷新整個(gè)表格
- (void)reloadData;
#pragma mark 刷新指定的行
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
#pragma mark 刷新指定的分組
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
#pragma mark 刪除時(shí)刷新指定的行數(shù)據(jù)
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
#pragma mark 添加時(shí)刷新指定的行數(shù)據(jù)
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
五缰揪、UITableViewCell的重用機(jī)制
在UITableView
內(nèi)部有一個(gè)緩存池陨享,專門用來緩存UITableViewCell
,因?yàn)?code>UITableView不是一下子顯示全部Cell钝腺,而是以 所見即所得 的方式抛姑,手機(jī)上看的見的Cell,才有存在的對(duì)象UITableViewCell
實(shí)例艳狐。具體表現(xiàn)如下:
- 每次顯示新的Cell的時(shí)候定硝,都是先從緩存池中取出對(duì)應(yīng)的
UITableViewCell
對(duì)象,進(jìn)行 重新初始化 顯示毫目。如果緩存池中沒有蔬啡,才創(chuàng)建新的UITableViewCell
對(duì)象 - 每當(dāng)某個(gè)Cell被移出 可見區(qū)域 外后,就會(huì)被 回收 到緩存池中
所以盡管要展示的數(shù)據(jù)巨大镀虐,但內(nèi)存中存在的UITableViewCell
也是有限的箱蟆,極大的降低了對(duì)內(nèi)存的需求。
# pragma mark - 在tableView:cellForRowAtIndexPath:方法中使用UITableView的重用機(jī)制
// 由于此方法調(diào)用十分頻繁刮便,cell的標(biāo)示聲明成靜態(tài)變量有利于性能優(yōu)化
static NSString *cellIdentifier = @"UITableViewCellIdentifierKey1";
// 首先根據(jù)標(biāo)識(shí)去緩存池取
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
// 如果緩存池沒有找到空猜,則重新創(chuàng)建并放到緩存池中
if(!cell){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier];
}
注意:
- 因?yàn)槭褂昧酥赜脵C(jī)制,你拿到的Cell上面也許本來就有數(shù)據(jù)恨旱,所以一定要對(duì)Cell里的所有子控件進(jìn)行初始化抄肖,否則會(huì)導(dǎo)致Cell數(shù)據(jù)混亂。
- 比如你第一個(gè)Cell設(shè)置了標(biāo)題窖杀,其他Cell都沒有設(shè)置標(biāo)題,你向下刷新的時(shí)候裙士,會(huì)發(fā)現(xiàn)總有一個(gè)Cell有標(biāo)題入客,但這個(gè)Cell不是第一個(gè)Cell,你頓時(shí)就懵逼了。所以Cell的重用時(shí)需要時(shí)刻注意初始化的問題桌硫。
六夭咬、系統(tǒng)自帶的UITableViewCell
系統(tǒng)自帶的UITableViewCell內(nèi)部控件示意圖
我們基本上很少使用系統(tǒng)自帶的
UITableViewCell
,樣式太過于死板了铆隘。
七卓舵、自定義Cell
基本步驟:
- 自定義類
XXXTableViewCell
,繼承UITableViewCell
- 重寫
-(id)initWithStyle:reuseIdentifier:
方法膀钠,添加子控件 - 最好重寫
layoutSubView
方法掏湾,設(shè)置子控件frame
- 然后在
UITableView
的代理方法tableView:cellForRowAtIndexPath:
中使用重用機(jī)制創(chuàng)建該類XXXTableViewCell
,再對(duì)cell進(jìn)行初始化
微博Cell子控件示意圖
微博Cell子控件示意圖
八肿嘲、MVC模式
MVC模式示意圖