UITableView

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樣式,是分組的.
圖1
圖2

可以看到兩種格式的區(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

  • 設置如下:
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

  1. 在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];
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容