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之旅 相互交流,共同窗习,共同进步!

欢迎访问本人微博 @卫志荣

相关文章
相关标签/搜索