UITableView

UITableView的樣式

UITableView是iOS開發(fā)中非常重要的控件之一,它能夠展示多行數(shù)據(jù),支持滾動(dòng).在大部分APP中都占有很大的比重.

  • UITableView的創(chuàng)建方式:
    • storyboard:直接拖到控制器中即可.
    • 代碼
    //代碼創(chuàng)建
    UITableView *tableView = [[UITableView alloc] init];
    //設(shè)置frame
    tableView.frame = self.view.bounds;
    [self.view addSubview:tableView];
  • UITableView有兩種樣式:plain和grouped.如圖所示,
    圖1是plain樣式即所有的cell都在黏在一起,沒有明顯的區(qū)分.圖2是grouped樣式,是分組的.
圖1
圖2

可以看到兩種格式的區(qū)別非常明顯.

在UITableView中,每一個(gè)單元格被稱為cell,如果想在UITableView中顯示數(shù)據(jù),需要設(shè)置UITableView中cell的數(shù)量及每個(gè)cell顯示的內(nèi)容.UITableView并不能直接顯示數(shù)據(jù),它需要設(shè)置數(shù)據(jù)源(datasource),數(shù)據(jù)源遵守<UITableViewDataSource>協(xié)議,并實(shí)現(xiàn)其中對(duì)應(yīng)的方法設(shè)置數(shù)據(jù)及內(nèi)容即可.

<UITableViewDataSource>中常用的方法:

@required(必須實(shí)現(xiàn)的)
    //返回第section行的row數(shù)量
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
    //返回第indexPath.row行的cell內(nèi)容
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
以上這兩個(gè)方法會(huì)調(diào)用一次或多次,次數(shù)根據(jù)設(shè)置的section數(shù)量及每個(gè)section的cell數(shù)量而定.在開發(fā)中一般通過模型來(lái)傳遞數(shù)據(jù),在控制器中創(chuàng)建一個(gè)數(shù)組接收模型數(shù)據(jù),然后加載到cell中顯示.

@optional(可選的)
     //返回section的數(shù)量,默認(rèn)為1
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; 
    //返回grouped樣式中每組的頭部標(biāo)題
    - (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; 
    //返回grouped樣式中每組的尾部標(biāo)題
    - (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;

UITableViewCell的創(chuàng)建及重用

UITableViewCell在創(chuàng)建時(shí),系統(tǒng)會(huì)自動(dòng)設(shè)置為懶加載狀態(tài).但為了高效利用每一個(gè)cell,我們需要設(shè)置cell的重用標(biāo)識(shí)(identfier),加載cell時(shí)先從緩存池中查找可用的cell.

UITableViewCell的創(chuàng)建方式1:純代碼

  • 設(shè)置如下:
  //設(shè)置indexPath.row行的cell內(nèi)容
  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{    
     //設(shè)置重用標(biāo)識(shí)
     static NSString *ID=@"cell";
     //根據(jù)重用標(biāo)識(shí)從緩存池中查找可用cell
     UITableViewCell *cell=[self.tableView dequeueReusableCellWithIdentifier:ID];
     //找不到可用cell,手動(dòng)創(chuàng)建標(biāo)識(shí)為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

  • 設(shè)置如下:
storyboard設(shè)置重用標(biāo)識(shí)

在代碼中實(shí)現(xiàn)以下方法:

  //設(shè)置indexPath.row行的cell內(nèi)容
  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{    
     //設(shè)置重用標(biāo)識(shí)
     static NSString *ID=@"cell";
     //根據(jù)重用標(biāo)識(shí)從緩存池中查找可用cell,如果找不到,系統(tǒng)會(huì)根據(jù)storyboard中的cell標(biāo)識(shí)創(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

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

    //先在控制器中對(duì)cell的標(biāo)識(shí)注冊(cè)
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
    
  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{    
     //設(shè)置重用標(biāo)識(shí)
     static NSString *ID=@"cell";
     //根據(jù)重用標(biāo)識(shí)從緩存池中查找可用cell,如果找不到,系統(tǒng)會(huì)根據(jù)注冊(cè)的cell標(biāo)識(shí)創(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的代理協(xié)議,可以實(shí)現(xiàn)UIScrollViewDelegate中的方法來(lái)監(jiān)聽UITableView的滾動(dòng)事件.

在UITableView中每個(gè)section的頭部或底部,如果想設(shè)置圖片,可以實(shí)現(xiàn)以下方法.

  //在section的底部區(qū)域顯示一個(gè)UIView控件
  - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{
    return expression;
}
  //在section的頭部區(qū)域顯示一個(gè)UIView控件
  - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
    return expression;
}

如果想監(jiān)聽點(diǎn)擊某一行,可以實(shí)現(xiàn)以下方法:

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

如果想設(shè)置tableView不顯示分割線,可以設(shè)置以下屬性

   self.tableView separatorStyle = UITableViewCellSeparatorStyleNone;

UITableViewCell中的控件其實(shí)都添加到了cell中的Content View上面,在自定義控件添加時(shí),需要調(diào)用
[cell.contentView addSubview:(nonnull UIView *)]方法,添加到cell的.contentView中去,這也是蘋果官方推薦添加的一種方式.

創(chuàng)建自定義等高cell方式1:storyboard

  1. 在storyboard中放入一個(gè)UITableViewController(或者UIViewController中嵌套一個(gè)UITableView),系統(tǒng)會(huì)默認(rèn)自帶一個(gè)cell.

2.更改cell的重用標(biāo)識(shí)(identfier)

3.給每個(gè)cell綁定一個(gè)tag,方便設(shè)置數(shù)據(jù).

4.在數(shù)據(jù)源方法中設(shè)置cell的顯示內(nèi)容

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *ID=@"cell";
        
    UITableViewCell *cell=[self.tableView dequeueReusableCellWithIdentifier:ID];
    
    //獲取模型數(shù)據(jù)
    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ā)中會(huì)比較不方便,不推薦這種自定義方法.

創(chuàng)建自定義等高cell方式2:自定義cell

1.新建一個(gè)類

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

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

4.在新建類.h文件中包含模型類,定義一個(gè)模型屬性接收模型數(shù)據(jù)

#import <UIKit/UIKit.h>
@class DLShop;

@interface DLShopCell : UITableViewCell
// 定義模型屬性,接收數(shù)據(jù)
@property(nonatomic,strong) DLShop *shop;
@end

5.在新建類.m文件中,導(dǎo)入模型頭文件,重寫模型屬性的set方法,設(shè)置傳入的模型數(shù)據(jù)到子控件>

@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:@"%@人已購(gòu)買",shop.buyCount];
    
}
@end

6.在控制器中實(shí)現(xiàn)數(shù)據(jù)源方法,設(shè)置數(shù)據(jù)

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *ID=@"cell";
    
    // 新建一個(gè)DLShopCell類型的cell,保證創(chuàng)建的cell是我們自定義的
    DLShopCell *cell=[self.tableView dequeueReusableCellWithIdentifier:ID];
    
    //獲取模型數(shù)據(jù)
    cell.shop = self.shops[indexPath.row];
    
    return cell;
}

自定義類名創(chuàng)建cell比較方便,能很好的封裝cell控件,設(shè)置數(shù)據(jù)也很方便.

創(chuàng)建自定義等高cell方式3:xib自定義cell

1.新建一個(gè)xib文件,名稱與自定義類名保持一致.

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

3.設(shè)置xib內(nèi)部cell的重用標(biāo)識(shí)

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

5.在自定義類.h文件中包含模型類,定義一個(gè)模型屬性接收模型數(shù)據(jù),同時(shí)提供一個(gè)類方法,將tableView傳進(jìn)去.

#import <UIKit/UIKit.h>
@class DLShop;

@interface DLShopCell : UITableViewCell
// 定義模型屬性,接收數(shù)據(jù)
@property(nonatomic,strong) DLShop *shop;

// 外界傳入tableView,返回DLShopCell類型的cell
+ (instancetype)cellWithTableView:(UITableView *)tableView;
@end

6.在.m文件中實(shí)現(xiàn)以上方法.

@implementation DLShopCell
//重寫模型屬性set方法設(shè)置傳入模型數(shù)據(jù)到子控件
-(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:@"%@人已購(gòu)買",shop.buyCount]; 
}
//實(shí)現(xiàn)cellWithTableView:將外界傳入tableView查找緩存池?cái)?shù)據(jù),如果沒有,創(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完美實(shí)現(xiàn)了控件的封裝,將控件的所有屬性都包裝在自己內(nèi)部,推薦使用xib自定義cell,方便后期維護(hù)及使用.

懶加載

在控制器中新建數(shù)組屬性保存模型數(shù)據(jù)時(shí),一般會(huì)采用懶加載思想.步驟如下:

1.在控制器文件中定義一個(gè)數(shù)組,保存?zhèn)魅氲哪P蛿?shù)據(jù).

@interface TestTableViewController ()
// 用來(lái)保存?zhèn)魅氲哪P蛿?shù)據(jù)
@property(nonatomic,strong) NSArray *shops;
@end

2.重寫屬性的get方法,用到時(shí)再調(diào)用該屬性,以實(shí)現(xiàn)懶加載.

- (NSArray *)shops{
    
    if (_shops == nil) {
        NSString *path = [[NSBundle mainBundle] pathForResource:@"shops.plist" ofType:nil];
        //取出字典數(shù)據(jù)轉(zhuǎn)為數(shù)組
        NSArray *dictArr = [NSArray arrayWithContentsOfFile:path];
        //創(chuàng)建一個(gè)空的可變數(shù)組接收模型數(shù)據(jù)
        NSMutableArray *dealArrM = [NSMutableArray array];
        //遍歷數(shù)組取出字典數(shù)據(jù)
        for (NSDictionary *dict in dictArr) {
            //定義模型接收字典數(shù)據(jù)
            DLShop *shop = [DLShop shopWithDict:dict];
            //將數(shù)據(jù)添加到模型
            [dealArrM addObject:shop];
        }//傳遞模型到成員變量中
        _shops = dealArrM;
    }
    return _shops;
}

設(shè)置tableview有值時(shí)才顯示分割線

- (void)viewDidLoad{
  [super ViewDidLoad];
  //設(shè)置tableview有值時(shí)才顯示分割線
  self.tableView.tableFooterView = [UIView alloc] init];
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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