序引
本系列文章將介紹iOS開發(fā)中的UITableView控件,將會分成四篇文章完整的講述UITableView的具體使用方法和注意點,文章編寫周期會長一些,由于本人還在學(xué)習(xí)iOS開發(fā)階段,有些東西可能會描述不對或錯誤,Markdown排版也不是特別好,歡迎各位讀者指點其中不對的地方。
本文主要涉及的知識點:
- UITableView的概念
- UITableView顯示數(shù)據(jù)的兩種樣式
- UITableView的使用步驟
- UITableView的常見屬性
- UITableViewCell的基本概念
- UITableViewCell的常見屬性
- UITableView的代理方法
- UITableViewController的講解
- UITableViewCell的重用
1. UITableView的概念
- 在iOS開發(fā)中,要實現(xiàn)展示列表數(shù)據(jù),就常用的做法就是使用UITableView
- UITbaleView繼承自UIScrollView,因此支持垂直滾動,而且性能極佳
2. UITableView顯示數(shù)據(jù)的兩種樣式
- 單組樣式
- UITableViewStylePlain
- 展示單組數(shù)據(jù),沒有分組
-
例如:
01.png
- 分組樣式
- UITableViewStyleGrouped
- 展示多組數(shù)據(jù),有分組,每一組可以有不同的行數(shù)
-
例如:
02.png
3. UITableView的使用步驟
-
第一步:設(shè)置數(shù)據(jù)源對象
self.tableView.dataSource = self;
- 數(shù)據(jù)源對象一般設(shè)置為當(dāng)前控制器
- 設(shè)置的語句寫在控制器的
- (void)viewDidLoad
方法中- (void)viewDidLoad { [super viewDidLoad]; // 設(shè)置數(shù)據(jù)源對象為當(dāng)前控制器 self.tableView.dataSource = self; }
-
第二步:設(shè)置的數(shù)據(jù)源對象要遵守協(xié)議
- 設(shè)置為數(shù)據(jù)源對象的類一定要遵守
UITableViewDataSource
協(xié)議@interface ViewController () <UITableViewDataSource> @end
- 設(shè)置為數(shù)據(jù)源對象的類一定要遵守
-
第三步:實現(xiàn)數(shù)據(jù)源協(xié)議中的方法
單組數(shù)據(jù)必須實現(xiàn)數(shù)據(jù)源中的兩個方法
多行數(shù)據(jù)必須實現(xiàn)數(shù)據(jù)源中的三個方法
-
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- 告訴tableView一共有多少組數(shù)據(jù)
- 單組數(shù)據(jù)可以不用實現(xiàn)(因為只有一組數(shù)據(jù),系統(tǒng)默認(rèn)為1),多組數(shù)據(jù)必須實現(xiàn)
- 參數(shù)section:傳入當(dāng)前是第幾組,當(dāng)樣式為單組數(shù)據(jù)的時候,section永遠(yuǎn)為0
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 4; }
-
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- 告訴tableView每一組有多少行數(shù)據(jù)
- 單組數(shù)據(jù)和多組數(shù)據(jù)都必須實現(xiàn)
- 參數(shù)section:傳入當(dāng)前是第幾組
- 參數(shù)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (section == 0) { return 2; // 第0組有兩行數(shù)據(jù) } else if (section == 1) { return 6; // 第1組有六行數(shù)據(jù) } else if (section == 2) { return 6; // 第2組有六行數(shù)據(jù) } else { return 1; // 第3組有一行數(shù)據(jù) } }
-
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- 告訴tableView每一行顯示的內(nèi)容
- tableView每一行的內(nèi)容一定是
UITableViewCell
- 單組數(shù)據(jù)和多組數(shù)據(jù)都必須實現(xiàn)
- 參數(shù)indexPath:indexPath有兩個屬性,
indexPath.section
傳入當(dāng)前是第幾組,indexPath.row
傳入當(dāng)前是第幾行- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [[UITableViewCell alloc] init]; if (indexPath.section == 0) { if (indexPath.row == 0) { // 第0組第0行顯示的數(shù)據(jù)為“通用” cell.textLabel.text = @"通用"; } else if (indexPath.row == 1) { // 第0組第1行顯示的數(shù)據(jù)為“隱私” cell.textLabel.text = @"隱私"; } } else { // 其他組顯示的數(shù)據(jù)為自己的組號和行號 cell.textLabel.text = [NSString stringWithFormat:@"%zd組%zd行-其他數(shù)據(jù)", indexPath.section,indexPath.row]; } return cell; }
-
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
- 告訴tableView每一組的頭部標(biāo)題
- 參數(shù)section:傳入當(dāng)前是第幾組
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { if (section == 0) { return @"頭部標(biāo)題"; } else { return @"頭部標(biāo)題"; } }
-
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
- 告訴tableView每一組的尾部標(biāo)題
- 參數(shù)section:傳入當(dāng)前是第幾組
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { if (section == 0) { return @"尾部標(biāo)題"; } else { return @"尾部標(biāo)題"; } }
4. UITableView的常見屬性
-
設(shè)置行高的高度:
屬性: @property (nonatomic) CGFloat rowHeight; 使用格式: self.tableView.rowHeight = 70; 說明: 默認(rèn)是44
-
設(shè)置每一組的頭部高度:
屬性: @property (nonatomic) CGFloat sectionHeaderHeight; 使用格式: self.tableView.sectionHeaderHeight = 50;
-
設(shè)置分割線的顏色:
屬性: @property (nonatomic, strong) UIColor *separatorColor 使用格式: self.tableView.separatorColor = [UIColor redColor]; 說明: 設(shè)置[UIColor clearColor]代表隱藏分割線,[UIColor clearColor]為透明色對象
-
設(shè)置分割線的樣式:
屬性: @property (nonatomic) UITableViewCellSeparatorStyle separatorStyle 使用格式: self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine; 枚舉UITableViewCellSeparatorStyle常用的枚舉元素: UITableViewCellSeparatorStyleNone // 隱藏分割線 UITableViewCellSeparatorStyleSingleLine // 默認(rèn)樣式 UITableViewCellSeparatorStyleSingleLineEtched // 僅支持在grouped樣式,但是和默認(rèn)樣式?jīng)]什么區(qū)別
-
設(shè)置表頭控件:
屬性: @property (nonatomic, strong) UIView *tableHeaderView; 使用格式: self.tableView.tableHeaderView = [[UISwitch alloc] init];
-
設(shè)置表尾控件:
屬性: @property (nonatomic, strong) UIView *tableFooterView; 使用格式: self.tableView.tableFooterView = [[UISwitch alloc] init];
5. UITableViewCell的基本概念
-
UITableView
的每一行都是一個UITableViewCell
-
UITableView
內(nèi)部有個默認(rèn)的子控件:contentView
,填充整個UITableViewCell
的父控件 -
UITableView
的子控件實質(zhì)都在contentView
6. UITableViewCell的常見屬性
-
設(shè)置cell右邊的指示控件:
屬性: @property (nonatomic, strong) UIView *accessoryView; 使用格式: cell.accessoryView = [[UISwitch alloc] init];
-
設(shè)置cell右邊的指示樣式:
屬性: @property (nonatomic) UITableViewCellAccessoryType accessoryType; 使用格式: cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 枚舉UITableViewCellSeparatorStyle常用的枚舉元素: UITableViewCellSeparatorStyleNone // 隱藏分割線 UITableViewCellSeparatorStyleSingleLine // 默認(rèn)樣式 UITableViewCellSeparatorStyleSingleLineEtched //
-
設(shè)置cell的選中樣式:
屬性: @property (nonatomic) UITableViewCellSelectionStyle selectionStyle; 使用格式: cell.selectionStyle = UITableViewCellSelectionStyleNone; 枚舉UITableViewCellSelectionStyle常用的枚舉元素: UITableViewCellSelectionStyleNone // 不能選中 UITableViewCellSelectionStyleBlue UITableViewCellSelectionStyleGray UITableViewCellSelectionStyleDefault
-
設(shè)置cell的背景控件:
屬性: @property (nonatomic, strong) UIView *backgroundView; 使用格式: UIView *bg = [[UIView alloc] init]; bg.backgroundColor = [UIColor redColor]; cell.backgroundView = bg;
-
設(shè)置cell的背景顏色:
屬性: @property(nullable, nonatomic,copy) UIColor *backgroundColor 使用格式: cell.backgroundColor = [UIColor blueColor]; 說明: 還可以設(shè)置cell的子控件背景圖片 cell.textLabel.backgroundColor = [UIColor greenColor];
-
設(shè)置cell選中的背景view:
屬性: @property (nonatomic, strong) UIView *selectedBackgroundView; 使用格式: UIView *seletedBg = [[UIView alloc] init]; seletedBg.backgroundColor = [UIColor purpleColor]; cell.selectedBackgroundView = seletedBg;
7. UITableView的代理方法
-
當(dāng)選中某一行cell的時候就會調(diào)用這個方法:
方法聲明: - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath; 使用格式: - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"選中第%zd行", indexPath.row); }
-
當(dāng)取消選中某一行cell的時候就會調(diào)用這個方法:
方法聲明: - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath; 使用格式: - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"取消選中第%zd行", indexPath.row); }
-
返回每一組的頭部控件:
方法聲明: - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section; 使用格式: - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { return [UIButton buttonWithType:UIButtonTypeContactAdd]; }
-
返回每一組的尾部控件:
方法聲明: - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section; 使用格式: - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { return [[UISwitch alloc] init]; }
-
返回每一組的頭部高度:
方法聲明: - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section; 使用格式: - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 100; }
-
返回每一組的尾部高度:
方法聲明: - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section; 使用格式: - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 100;
}
- 返回每一行cell的高度:
```objc
方法聲明:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
使用格式:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) {
return 100;
} else {
return 50;
}
}
8. UITableViewController的講解
-
將控制器設(shè)置為UITableView的方法和步驟
- 第一步:創(chuàng)建新的類或修改原有的ViewController類,繼承自UITableViewController
- 第二步:在Main.storyboard中刪除自帶的
UIViewController
控制器,然后往里面拖一個UITableViewController
控制器
03.png - 第三步:修改新拖進(jìn)來的
TableViewController
控制器的自定義類名為第一步中繼承自UITableViewController
類的類名
04.png - 第四步:勾選
TableViewController
控制器為程序啟動第一個加載的控制器
05.png
注意點:
tableVieController
有個tableView
屬性,指向一個tableView
tableView
的dataSource
和delegate
屬性指向的就是這個控制器,并且這個控制器已經(jīng)遵守了UITableViewDataSource
和UITableViewDelegate
每個控制器的內(nèi)部都有一個
view
屬性,在tableVieController
中,view
和tableView
屬性指向的是同一個對象(控制器的view就是tableView)
9. UITableViewCell的重用
- 原因
- iOS設(shè)備的內(nèi)存有限,如果用UITableView顯示成千上萬條數(shù)據(jù),就需要成千上萬個
UITableViewCell
對象的話,那將會耗盡iOS設(shè)備的內(nèi)存 - 要解決該問題,需要重用
UITableViewCell
對象
- iOS設(shè)備的內(nèi)存有限,如果用UITableView顯示成千上萬條數(shù)據(jù),就需要成千上萬個
- 原理:
- 當(dāng)滾動列表時,部分
UITableViewCell
會移出窗口,UITableView
會將窗口外的UITableViewCell
放入一個緩存池中,等待重用 - 當(dāng)
UITableView
要求dataSource
返回UITableViewCell
時,dataSource
會先查看這個對象池,如果池中有未使用的UITableViewCell
,dataSource
會用新的數(shù)據(jù)配置這個UITableViewCell
,然后返回給UITableView
,重新顯示到窗口中,從而避免創(chuàng)建新的UITableViewCell
對象
- 當(dāng)滾動列表時,部分
- Cell重用的實現(xiàn)代碼
-
方法一:
- 定義一個cell的重用標(biāo)識
- 根據(jù)這個ID去緩存池中看有沒有可循環(huán)利用的cell
- 如果緩存池中沒有可循環(huán)利用的cell,自己創(chuàng)建
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 1. 定義一個重用標(biāo)識 static NSString *ID = @"A"; // 2. 根據(jù)這個ID去緩存池中看有沒有可循環(huán)利用的cell UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"A"]; // 3. 如果緩存池中沒有可循環(huán)利用的cell, 自己創(chuàng)建 if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"A"]; } return cell; }
-
方法二:
- 定義一個cell的重用標(biāo)識
- 根據(jù)這個ID去緩存池中看有沒有可循環(huán)利用的cell
- 如果緩存池中沒有會看有沒有根據(jù)ID這個標(biāo)識注冊對應(yīng)的cell類型
- 如果有注冊,會根據(jù)這個ID創(chuàng)建對應(yīng)的類型的cell,并且會綁定這個ID標(biāo)識,返回這個cell
// 1. 定義一個重用標(biāo)識 static NSString *ID = @"A"; - (void)viewDidLoad { [super viewDidLoad]; // 3. 根據(jù)ID 這個標(biāo)識 注冊 對應(yīng)的cell類型是UITableViewCell [self.tableView registerClass:[YTTableViewCell class] forCellReuseIdentifier:ID]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 2. 根據(jù)這個ID去緩存池中看有沒有可循環(huán)利用的cell YTTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; return cell; }
-