UITableView的樣式
UITableView是iOS開發(fā)中非常重要的控件之一,它能夠展示多行數據,支持滾動.在大部分APP中都占有很大的比重.
- UITableView的創(chuàng)建方式:
- storyboard:直接拖到控制器中即可.
- 代碼
//代碼創(chuàng)建
UITableView *tableView = [[UITableView alloc] init];
//設置frame
tableView.frame = self.view.bounds;
[self.view addSubview:tableView];
- UITableView有兩種樣式:plain和grouped.如圖所示,
圖1是plain樣式即所有的cell都在黏在一起,沒有明顯的區(qū)分.圖2是grouped樣式,是分組的.


可以看到兩種格式的區(qū)別非常明顯.
在UITableView中,每一個單元格被稱為cell,如果想在UITableView中顯示數據,需要設置UITableView中cell的數量及每個cell顯示的內容.UITableView并不能直接顯示數據,它需要設置數據源(datasource),數據源遵守<UITableViewDataSource>協議,并實現其中對應的方法設置數據及內容即可.
<UITableViewDataSource>中常用的方法:
@required(必須實現的)
//返回第section行的row數量
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
//返回第indexPath.row行的cell內容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
以上這兩個方法會調用一次或多次,次數根據設置的section數量及每個section的cell數量而定.在開發(fā)中一般通過模型來傳遞數據,在控制器中創(chuàng)建一個數組接收模型數據,然后加載到cell中顯示.
@optional(可選的)
//返回section的數量,默認為1
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
//返回grouped樣式中每組的頭部標題
- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
//返回grouped樣式中每組的尾部標題
- (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
UITableViewCell的創(chuàng)建及重用
UITableViewCell在創(chuàng)建時,系統(tǒng)會自動設置為懶加載狀態(tài).但為了高效利用每一個cell,我們需要設置cell的重用標識(identfier),加載cell時先從緩存池中查找可用的cell.
UITableViewCell的創(chuàng)建方式1:純代碼
- 設置如下:
//設置indexPath.row行的cell內容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//設置重用標識
static NSString *ID=@"cell";
//根據重用標識從緩存池中查找可用cell
UITableViewCell *cell=[self.tableView dequeueReusableCellWithIdentifier:ID];
//找不到可用cell,手動創(chuàng)建標識為ID的cell
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
}
//板式輸出
cell.textLabel.text = [NSString stringWithFormat:@"test--%zd",indexPath.row];
//返回cell
return cell;
}
UITableViewCell的創(chuàng)建方式2:storyboard
- 設置如下:

在代碼中實現以下方法:
//設置indexPath.row行的cell內容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//設置重用標識
static NSString *ID=@"cell";
//根據重用標識從緩存池中查找可用cell,如果找不到,系統(tǒng)會根據storyboard中的cell標識創(chuàng)建cell.
UITableViewCell *cell=[self.tableView dequeueReusableCellWithIdentifier:ID];
//板式輸出
cell.textLabel.text = [NSString stringWithFormat:@"test--%zd",indexPath.row];
//返回cell
return cell;
}
UITableViewCell的創(chuàng)建方式3:register
實現方法如下:
//先在控制器中對cell的標識注冊
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//設置重用標識
static NSString *ID=@"cell";
//根據重用標識從緩存池中查找可用cell,如果找不到,系統(tǒng)會根據注冊的cell標識創(chuàng)建cell.
UITableViewCell *cell=[self.tableView dequeueReusableCellWithIdentifier:ID];
//板式輸出
cell.textLabel.text = [NSString stringWithFormat:@"test--%zd",indexPath.row];
//返回cell
return cell;
}
UITableView及UITableViewCell的一些屬性
UITableView繼承自UIScrollView,如果成為了UITableView的代理,也就意味著同樣遵守了UIScrollView的代理協議,可以實現UIScrollViewDelegate中的方法來監(jiān)聽UITableView的滾動事件.
在UITableView中每個section的頭部或底部,如果想設置圖片,可以實現以下方法.
//在section的底部區(qū)域顯示一個UIView控件
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{
return expression;
}
//在section的頭部區(qū)域顯示一個UIView控件
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
return expression;
}
如果想監(jiān)聽點擊某一行,可以實現以下方法:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
如果想設置tableView不顯示分割線,可以設置以下屬性
self.tableView separatorStyle = UITableViewCellSeparatorStyleNone;
UITableViewCell中的控件其實都添加到了cell中的Content View上面,在自定義控件添加時,需要調用
[cell.contentView addSubview:(nonnull UIView *)]方法,添加到cell的.contentView中去,這也是蘋果官方推薦添加的一種方式.
創(chuàng)建自定義等高cell方式1:storyboard
- 在storyboard中放入一個UITableViewController(或者UIViewController中嵌套一個UITableView),系統(tǒng)會默認自帶一個cell.

2.更改cell的重用標識(identfier)

3.給每個cell綁定一個tag,方便設置數據.

4.在數據源方法中設置cell的顯示內容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID=@"cell";
UITableViewCell *cell=[self.tableView dequeueReusableCellWithIdentifier:ID];
//獲取模型數據
DLShop *shop = self.shops[indexPath.row];
//給cell賦值
UIImageView *iconView = (UIImageView *)[cell viewWithTag:1];
iconView.image = [UIImage imageNamed:shop.icon];
UILabel *titleLabel = (UILabel *)[cell viewWithTag:2];
titleLabel.text = shop.title;
UILabel *priceLabel = (UILabel *)[cell viewWithTag:3];
priceLabel.text = shop.price;
UILabel *buyCount = (UILabel *)[cell viewWithTag:4];
buyCount.text = shop.buyCount;
return cell;
}
storyboard中自定義cell需要用到tag,開發(fā)中會比較不方便,不推薦這種自定義方法.
創(chuàng)建自定義等高cell方式2:自定義cell
1.新建一個類

2.在storyboard中選中cell,修改class為類名

3.將cell中的控件拖線至新建類中

4.在新建類.h文件中包含模型類,定義一個模型屬性接收模型數據
#import <UIKit/UIKit.h>
@class DLShop;
@interface DLShopCell : UITableViewCell
// 定義模型屬性,接收數據
@property(nonatomic,strong) DLShop *shop;
@end
5.在新建類.m文件中,導入模型頭文件,重寫模型屬性的set方法,設置傳入的模型數據到子控件>
@implementation DLShopCell
-(void)setShop:(DLShop *)shop{
_shop = shop;
self.icon.image = [UIImage imageNamed:shop.icon];
self.title.text = shop.title;
self.price.text = [NSString stringWithFormat:@"¥%@",shop.price];
self.buyCount.text = [NSString stringWithFormat:@"%@人已購買",shop.buyCount];
}
@end
6.在控制器中實現數據源方法,設置數據
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID=@"cell";
// 新建一個DLShopCell類型的cell,保證創(chuàng)建的cell是我們自定義的
DLShopCell *cell=[self.tableView dequeueReusableCellWithIdentifier:ID];
//獲取模型數據
cell.shop = self.shops[indexPath.row];
return cell;
}
自定義類名創(chuàng)建cell比較方便,能很好的封裝cell控件,設置數據也很方便.
創(chuàng)建自定義等高cell方式3:xib自定義cell
1.新建一個xib文件,名稱與自定義類名保持一致.

2.修改xib的class為自定義類的名稱,保證創(chuàng)建時能夠找到xib文件

3.設置xib內部cell的重用標識

4.從xib拖線至自定義類中

5.在自定義類.h文件中包含模型類,定義一個模型屬性接收模型數據,同時提供一個類方法,將tableView傳進去.
#import <UIKit/UIKit.h>
@class DLShop;
@interface DLShopCell : UITableViewCell
// 定義模型屬性,接收數據
@property(nonatomic,strong) DLShop *shop;
// 外界傳入tableView,返回DLShopCell類型的cell
+ (instancetype)cellWithTableView:(UITableView *)tableView;
@end
6.在.m文件中實現以上方法.
@implementation DLShopCell
//重寫模型屬性set方法設置傳入模型數據到子控件
-(void)setShop:(DLShop *)shop{
_shop = shop;
self.icon.image = [UIImage imageNamed:shop.icon];
self.title.text = shop.title;
self.price.text = [NSString stringWithFormat:@"¥%@",shop.price];
self.buyCount.text = [NSString stringWithFormat:@"%@人已購買",shop.buyCount];
}
//實現cellWithTableView:將外界傳入tableView查找緩存池數據,如果沒有,創(chuàng)建并返回DLShopCell類型的cell
+ (instancetype)cellWithTableView:(UITableView *)tableView{
static NSString *ID = @"cell";
DLShopCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([DLShopCell class]) owner:nil options:nil] lastObject];
}
return cell;
}
@end
xib自定義cell完美實現了控件的封裝,將控件的所有屬性都包裝在自己內部,推薦使用xib自定義cell,方便后期維護及使用.
懶加載
在控制器中新建數組屬性保存模型數據時,一般會采用懶加載思想.步驟如下:
1.在控制器文件中定義一個數組,保存?zhèn)魅氲哪P蛿祿?
@interface TestTableViewController ()
// 用來保存?zhèn)魅氲哪P蛿祿?@property(nonatomic,strong) NSArray *shops;
@end
2.重寫屬性的get方法,用到時再調用該屬性,以實現懶加載.
- (NSArray *)shops{
if (_shops == nil) {
NSString *path = [[NSBundle mainBundle] pathForResource:@"shops.plist" ofType:nil];
//取出字典數據轉為數組
NSArray *dictArr = [NSArray arrayWithContentsOfFile:path];
//創(chuàng)建一個空的可變數組接收模型數據
NSMutableArray *dealArrM = [NSMutableArray array];
//遍歷數組取出字典數據
for (NSDictionary *dict in dictArr) {
//定義模型接收字典數據
DLShop *shop = [DLShop shopWithDict:dict];
//將數據添加到模型
[dealArrM addObject:shop];
}//傳遞模型到成員變量中
_shops = dealArrM;
}
return _shops;
}
設置tableview有值時才顯示分割線
- (void)viewDidLoad{
[super ViewDidLoad];
//設置tableview有值時才顯示分割線
self.tableView.tableFooterView = [UIView alloc] init];
}