UITableView 系列之自定義 UITableViewCell

原本不打算寫UITableView的,由於網上已經有不少這方面的文章,尤爲是 趣味蘋果開發中的TableViewController系列 已經有很詳細的講解了。可是羣裏仍是有不少童鞋會問這方面的問題,因此在這裏以本身的理解方式比劃一下。html

讓咱們先來看一張從模擬器截下來的圖:ios

上圖是一個UITableView列表,紅色的一、二、三、四、5...是一個個的UITableViewCell。數組

從這張截圖咱們能夠看出來 UITableView 是由一系列 UITableViewCell 組成的列表,由此咱們能夠知道 UITableViewCell 在 UITableVeiw 中的重要性了。學習

在真實地項目中,UITableViewCell 中的各項內容的排列都不一樣(如上圖4中的 2013年、全國等),它自帶的那幾種樣式根本沒法知足咱們的需求,因此這就須要咱們來自定義本身的Cell(下文中的Cell都表示UITableViewCell)了。atom

以上圖中的Cell爲例,咱們來自定義一個UITableViewCell。首先咱們來建立一個應用——CustomTableVeiwCellDemo,打開XCode,選擇File -> New -> Project...,以下圖所示:spa

而後選擇iOS->Application->Single View Application,而後點Next,以下圖所示:代理

在Product Name中輸入「CustomTableVeiwCellDemo」,其餘設置部分參照下圖:code

 

而後點Next,保存到磁盤適當的位置,至此咱們的Xcode應該是下圖這個樣子:htm

工程建立完成了,而後開始咱們的UITableView之旅吧。對象

首先咱們須要有一個UITableView,那麼咱們給上圖中的WViewController.xib上拖拽一個UITableVeiw,而後綁定UITableView的dataSource與delegate到WViewController上,以下圖:

咱們給UITableView設置個名稱爲tableView

並給WViewController.h 設置 dataSource、delegate的代理,代碼以下:

//
//  WViewController.h
//  CustomTableVeiwCellDemo
//
//  Created by wzrong on 13-8-15.
//  Copyright (c) 2013年 wzrong. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface WViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>

@property (strong, nonatomic) IBOutlet UITableView *tableView;

@end

而後在WViewController.m中實現dataSource與delegate的部分方法,如 UITableView的區段數、UITableView的行數、指定行的UITableVeiwCell、單擊單元格的處理等

#pragma mark - UITableView methods
/**
 一、返回 UITableView 的區段數
 */
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    
}

/**
 二、返回 UITableView 的行數
 */
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    
}

/**
 三、設置行的高度
 */
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    
}

/**
 四、返回指定的 row 的 cell
 */
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    
}

/**
 五、點擊單元格時的處理
 */
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    
} 

接下來咱們按照上邊註釋的步驟來填充方法

一、本例中咱們只須要一個區段,因此返回1就ok了。

/**
 一、返回 UITableView 的區段數
 */
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;      
}

二、要知道返回的行數,首先咱們須要知道有多少條數據,到目前爲止,咱們尚未定義要顯示的數據,因此先讓咱們來定義要顯示在UITableView上的數據吧。

  2.1 咱們須要顯示的是年份、省份、標題,因此首先咱們定義一個試卷模型WPaperModel,用來存放顯示的這些屬性。

  右鍵工程->New Group,建立一個組Model,

  

  選擇Model,在點擊下圖1的位置,建立一個Model文件夾與之相關聯

  

  在Model裏邊添加文件WPaperModel,並添加相應的屬性,並初始化模型對象,代碼以下:

 

  WPaperModel.h

//
//  WPaperModel.h
//  CustomTableVeiwCellDemo
//
//  Created by wzrong on 13-8-15.
//  Copyright (c) 2013年 wzrong. All rights reserved.
//
//  試卷模型
//  

#import <Foundation/Foundation.h>

@interface WPaperModel : NSObject

@property (nonatomic, assign) NSInteger paperID;        // 試卷代號
@property (nonatomic, strong) NSString *paperYear;      // 試卷所屬年份
@property (nonatomic, strong) NSString *paperProvince;  // 試卷所屬省份
@property (nonatomic, strong) NSString *paperTitle;     // 試卷標題

/**
 初始化試卷模型對象
 @param paperId     試卷代號
 @param year        試卷年份
 @param province    試卷省份
 @param title       試卷標題
 */
- (id)initWithPaperID:(NSInteger)paperId
              paperYear:(NSString *)year
          paperProvince:(NSString *)province
             paperTitle:(NSString *)title;

@end

  WPaperModel.m

//
//  WPaperModel.m
//  CustomTableVeiwCellDemo
//
//  Created by wzrong on 13-8-15.
//  Copyright (c) 2013年 wzrong. All rights reserved.
//
//  試卷模型
//

#import "WPaperModel.h"

@implementation WPaperModel

/**
 初始化試卷模型對象
 @param paperId     試卷代號
 @param year        試卷年份
 @param province    試卷省份
 @param title       試卷標題
 */
- (id)initWithPaperID:(NSInteger)paperId
              paperYear:(NSString *)year
          paperProvince:(NSString *)province
             paperTitle:(NSString *)title{
    self = [super init];
    
    if (self) {
        self.paperID        = paperId;
        self.paperYear      = year;
        self.paperProvince  = province;
        self.paperTitle     = title;
    }
    
    return self;
}

@end

  2.2 在WViewController.m中定義要顯示的數據,把這些數據初始化到數據模型中,並把數據模型添加到要展現在UITableView的列表集合中,代碼以下:

  定義數據數組與試卷列表

@interface WViewController (){
    NSArray *_dataArray;        // 數據數組
    NSMutableArray *_paperList; // 試卷列表
}

  初始化數據數組、試卷列表與試卷模型,並把試卷模型添加到試卷列表中

  

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 初始化數據數組
    _dataArray = @[@[@"2013", @"北京", @"2012-2013學年北京市石景山區初一下學期期末考試數學試卷(帶解析)"],
                   @[@"2013", @"江蘇", @"2012-2013學年江蘇蘇州市景範中學初二第二學期期末考試數學試卷(帶解析)"],
                   @[@"2013", @"湖北", @"2013年湖北省恩施州初中數學評價《實數與代數式》單元試卷(一)(帶解析)"],
                   @[@"2013", @"全國", @"2013人教版初中數學七年級上冊第一章有理數練習卷(帶解析)"],
                   @[@"2013", @"湖北", @"2013年初中畢業升學考試(湖北十堰卷)數學(帶解析)"]];
    
    // 初始化試卷列表
    _paperList = [[NSMutableArray alloc]init];
    for (int i=0; i<_dataArray.count; i++) {
        // 初始化試卷模型
        WPaperModel *paperModel = [[WPaperModel alloc]initWithPaperID:i
                                                            paperYear:_dataArray[i][0]
                                                        paperProvince:_dataArray[i][1]
                                                           paperTitle:_dataArray[i][2]];
        // 添加試卷模型到試卷列表中
        [_paperList addObject:paperModel];
    }
}

  2.3 至此咱們知道了要展現在UITableView上邊的數據列表爲_paperList了,那麼也就知道了UITableView的行數了,因此就能夠設置行數了

/**
 二、返回 UITableView 的行數
 */
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return _paperList.count;
}

三、因爲咱們要自定義Cell,因此行的高度也就是自定義Cell的高度,接下來咱們就自定義Cell,起名爲 WPaperCell

  3.1 與上邊2.1相似,先創建一個View組,而後關聯到View文件夾中,再而後在View中建立WPaperCell,以下圖:

  

  3.2 建立完成後,咱們爲WPaperCell創建相對應的WPaperCell.xib文件,以下圖咱們選擇iOS -> Use Interface -> Empty,而後點擊Next

  

  而後拖拽一個UITableViewCell到WPaperCell.xib上,並與WPaperCell類關聯

  

  3.3 給Cell上拖拽3個UILabel,用來顯示年、省份、標題,設置Identifier標識符爲paperCell,Accessory的值爲Disclosure Indicator,以下圖:

  

  上圖中UILabel的線框,能夠參考 iOS 開發問題集錦(二) 中的第2個問題。

  3.4 給3個UILabel設置名稱,並初始化,代碼以下:

  WPaperCell.h

//
//  WPaperCell.h
//  CustomTableVeiwCellDemo
//
//  Created by wzrong on 13-8-15.
//  Copyright (c) 2013年 wzrong. All rights reserved.
//
//  自定義UITableViewCell
//  

#import <UIKit/UIKit.h>
#import "WPaperModel.h"

@interface WPaperCell : UITableViewCell

@property (strong, nonatomic) IBOutlet UILabel *lblYear;        // 年標籤 
@property (strong, nonatomic) IBOutlet UILabel *lblProvince;    // 省份標籤
@property (strong, nonatomic) IBOutlet UILabel *lblTitle;       // 標題標籤

/**
 設置Cell
 */
-(void)setupCell:(WPaperModel *)model;

@end

  WPaperCell.m 

//
//  WPaperCell.m
//  CustomTableVeiwCellDemo
//
//  Created by wzrong on 13-8-15.
//  Copyright (c) 2013年 wzrong. All rights reserved.
//

#import "WPaperCell.h"

@implementation WPaperCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

/**
 設置Cell
 */
-(void)setupCell:(WPaperModel *)model{
    self.lblYear.text       = model.paperYear;
    self.lblProvince.text   = model.paperProvince;
    self.lblTitle.text      = model.paperTitle;
}

@end

  3.5 因爲剛自定義的Cell的窗口高度爲88,因此設置行高爲88

/**
 三、設置行的高度
 */
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return 88.0f;
}

四、返回指定的行,因爲是自定義的Cell,因此此處須要返回WPaperCell,首先導入 #import "WPaperCell.h",而後設置,這裏有兩種設置方式。

  設置方式1:

/**
 四、返回指定的 row 的 cell
 */
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    // 1. cell標識符,使cell可以重用
    static NSString *paperCell = @"paperCell";
    
    // 2. 註冊自定義Cell的到TableView中,並設置cell標識符爲paperCell
    static BOOL isRegNib = NO;
    if (!isRegNib) {
        [tableView registerNib:[UINib nibWithNibName:@"WPaperCell" bundle:nil] forCellReuseIdentifier:paperCell];
        isRegNib = YES;
    }
    
    // 3. 從TableView中獲取標識符爲paperCell的Cell
    WPaperCell *cell = [tableView dequeueReusableCellWithIdentifier:paperCell];
    
    // 4. 設置單元格屬性
    [cell setupCell:_paperList[indexPath.row]];
    
    return cell;
}

  設置方式2:  

/**
 四、返回指定的 row 的 cell
 */
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    // 1. cell標示符,使cell可以重用
    static NSString *paperCell = @"paperCell";
    // 2. 從TableView中獲取標示符爲paperCell的Cell
    WPaperCell *cell = (WPaperCell *)[tableView dequeueReusableCellWithIdentifier:paperCell];
    // 若是 cell = nil , 則表示 tableView 中沒有可用的閒置cell
    if(cell == nil){
        // 3. 把 WPaperCell.xib 放入數組中
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"WPaperCell" owner:self options:nil] ;
        
        // 獲取nib中的第一個對象
        for (id oneObject in nib){
            // 判斷獲取的對象是否爲自定義cell
            if ([oneObject isKindOfClass:[WPaperCell class]]){
                // 4. 修改 cell 對象屬性
                cell = [(WPaperCell *)oneObject initWithStyle:UITableViewCellStyleDefault reuseIdentifier:paperCell];
            }
        }
    }
    // 5. 設置單元格屬性
    [cell setupCell:_paperList[indexPath.row]];
    return cell;
}

 

五、點擊單元格時,輸出省份,代碼以下:

/**
 五、點擊單元格時的處理
 */
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    WPaperModel *paperModel = _paperList[indexPath.row];
    NSLog(@"paper province -> %@", paperModel.paperProvince);
}

OK,大功告成,運行一下,看看效果:

 

代碼傳送門:CustomTableViewCell

 

著做權聲明:本文由 http://wzrong.cnblogs.com 或者 http://iostour.diandian.com 原創,歡迎轉載分享。 請尊重做者勞動,轉載時保留該聲明和做者博客連接,謝謝!

 


 

原創文章,如需轉載請註明出處,謝謝!

歡迎訪問本人技術微博 @iOS之旅 相互交流,共同窗習,共同進步!

歡迎訪問本人微博 @衛志榮

相關文章
相關標籤/搜索