UI 一一 自定义等高cell (XIB方式)

来源:互联网 发布:淘宝店主照片认证 编辑:程序博客网 时间:2024/05/16 15:33

使用纯代码的方式自定义等高cell的两种方式(Frame,Autolayout)

已经在我的这两篇博客中介绍:   

UI 一一 自定义等高cell (纯代码-Frame)方式   和   

UI 一一 自定义等高cell (纯代码-Autolayout)方式

接下来继续搞自定义等高cell,通过xib的方式,再后来就是使用storyboard的方式了.是不是感觉好多.

其实并不多.实际开发中掌握一种适合自己的就行.因为这些方式的思路和代码几乎相同!

效果图都是一样的:


实现思路及简要过程:

新建一个继承自UITableViewCell的子类,比如ZYTgCell

@interface ZYTgCell : UITableViewCell@end

新建一个xib文件(文件名最好跟类名一致,比如ZYTgCell.xib)

  • 修改cell的class为ZYTgCell


  • 绑定循环利用标识


  • 添加子控件,设置子控件约束


  • 将子控件连线到类扩展中
@interface ZYTgCell()@property (weak, nonatomic) IBOutlet UIImageView *iconImageView;@property (weak, nonatomic) IBOutlet UILabel *titleLabel;@property (weak, nonatomic) IBOutlet UILabel *priceLabel;@property (weak, nonatomic) IBOutlet UILabel *buyCountLabel;@end

在ZYTgCell.h文件中提供一个模型属性,比如ZYTg模型

@class ZYTg;@interface ZYTgCell : UITableViewCell/** 团购模型数据 */@property (nonatomic, strong) ZYTg *tg;@end

在ZYTgCell.m中重写模型属性的set方法

  • 在set方法中给子控件设置模型数据
- (void)setTg:(ZYTg *)tg{    _tg = tg;    // .......}

在控制器中

  • 注册xib文件
[self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([ZYTgCell class]) bundle:nil] forCellReuseIdentifier:ID];
  • 给cell传递模型数据
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{    // 访问缓存池    ZYTgCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];    // 设置数据(传递模型数据)    cell.tg = self.tgs[indexPath.row];    return cell;}

这里有些注意点:

1. 我们之前使用纯代码方式来自定义cell的时候,注册文件使用的是这个方法:

[self.tableView registerClass:[ZYTgCell class] forCellReuseIdentifier:ID];


使用xib创建cell的时候使用的是这个方法:

[self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([ZYTgCell class]) bundle:nil] forCellReuseIdentifier:ID];


为什么不可以使用上面的注册方法呢?

因为使用上面的那个注册方法,当缓存池中没有可用的cell的时候,就会自己去创建cell,创建cell的时候,就会调用调用initWithStyle这个方法,

这个方法是用来创建子控件,并设置子控件的一些初始化值.而我们是通过创建xib文件的方法创建子控件,所以根本不会使用到这个方法.

所以我们要使用下面的方法来注册,实现优化cell.


2. 在xib文件中,一般在identifier中绑定重用标识.


具体实现代码如下: 

ZYTg 文件

// 注意: ZYTg模型中,不需要再把字典中的数据,传到这个数据模型中,

因为我们使用了第三方框架MJExtension,这个框架中有需要快速转成模型的方法.使用这个框架会方便很多.

它会自动加载plist中的数据,并赋值给数据模型.

@interface ZYTg : NSObject/** 图标 */@property (nonatomic, copy) NSString *icon;/** 标题 */@property (nonatomic, copy) NSString *title;/** 价格 */@property (nonatomic, copy) NSString *price;/** 购买数 */@property (nonatomic, copy) NSString *buyCount;@end@implementation ZYTg@end

ZYTgCell.xib文件




ZYTgCell文件


#import <UIKit/UIKit.h>@class ZYTg;@interface ZYTgCell : UITableViewCell/** ZYTg模型 */@property(nonatomic,strong)ZYTg * tg;@end#import "ZYTg.h"@interface ZYTgCell ()@property (weak, nonatomic) IBOutlet UIImageView *iconImageView;@property (weak, nonatomic) IBOutlet UILabel *titleLabel;@property (weak, nonatomic) IBOutlet UILabel *priceLabel;@property (weak, nonatomic) IBOutlet UILabel *buyCountLabel;@end@implementation ZYTgCell// 重写set方法,设置数据- (void)setTg:(ZYTg *)tg{    _tg = tg;    self.iconImageView.image = [UIImage imageNamed:tg.icon];    self.titleLabel.text = tg.title;    self.priceLabel.text = [NSString stringWithFormat:@"¥%@",tg.price];    self.buyCountLabel.text = [NSString stringWithFormat:@"%@人已购买",tg.buyCount];    }@end



ViewController 文件

#import "ViewController.h"#import "ZYTgCell.h"#import "ZYTg.h"#import "MJExtension.h"@interface ViewController ()/** 所有的团购数据 */@property (nonatomic, strong) NSArray *tgs;@end@implementation ViewController// 使用第三方框架加载plist数据- (NSArray *)tgs{    if (_tgs == nil) {        _tgs = [ZYTg mj_objectArrayWithFilename:@"tgs.plist"];    }    return _tgs;}NSString *ID = @"tg";- (void)viewDidLoad {    [super viewDidLoad];     self.tableView.rowHeight = 80;        //这种方法不会实现优化,因为最终转换为initWithStyle,通过xib的方式创建cell,不会调用initWithStyle方法//    [self.tableView registerClass: [ZYTgCell class]forCellReuseIdentifier:ID];        // 注册的方法(优化)    [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([ZYTgCell class]) bundle:nil] forCellReuseIdentifier:ID];    }// 隐藏状态栏- (BOOL)prefersStatusBarHidden{    return YES;}#pragma -mark 数据源方法/** 有多少行数据 */- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{    return self.tgs.count;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{    // 创建一个重用标识    // 访问缓存池//    static NSString *ID = @"tg";    ZYTgCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];        // 判断缓存池中是否空的,如果为空就创建//    if (cell == nil) {//        // 在xib中的identifier中设置标识为tg,就可以在缓存池中取到重用的cell//        cell = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([ZYTgCell class]) owner:nil options:nil] lastObject];//    }        // 设置数据(传递数据模型)    cell.tg = self.tgs[indexPath.row];        return cell;}@end

比如又有一个需求:

不同类型的cell共存.也就是说在一个UITableView中显示不同类型的cell.

要实现这种需求: 

1. 就需要再创建一个继承UITableViewCell的子类,比如叫ZYTestCell

2. 再创建一个xib文件,并设置class为ZYTestCell.

3. 设置标识

4. 在控制器的方法中来根据indexPath.row 行号来使用这个cell. 

这样就实现了等高且不同类型的cell同时出现在UITableView中.其实这种需求也是有的.

比如你在手机上看网易新闻的时候,突然加载一段广告,这个广告也在UITableView上显示,其实就是一个不同类型的cell.


具体代码(我把上面的代码稍作修改)

ViewController 文件

#import "ViewController.h"#import "ZYTgCell.h"#import "ZYTg.h"#import "MJExtension.h"#import "ZYTestCell.h"@interface ViewController ()/** 所有的团购数据 */@property (nonatomic, strong) NSArray *tgs;@end@implementation ViewController// 使用第三方框架加载plist数据- (NSArray *)tgs{    if (_tgs == nil) {        _tgs = [ZYTg mj_objectArrayWithFilename:@"tgs.plist"];    }    return _tgs;}NSString *tgID = @"IDtg";NSString *testID = @"testTg";- (void)viewDidLoad {    [super viewDidLoad];     self.tableView.rowHeight = 80;        //这种方法不会实现优化,因为最终转换为initWithStyle,通过xib的方式创建cell,不会调用initWithStyle方法//    [self.tableView registerClass: [ZYTgCell class]forCellReuseIdentifier:ID];        // 注册的方法(优化)    [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([ZYTgCell class]) bundle:nil] forCellReuseIdentifier:tgID];        [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([ZYTestCell class]) bundle:nil] forCellReuseIdentifier:testID];    }// 隐藏状态栏- (BOOL)prefersStatusBarHidden{    return YES;}#pragma -mark 数据源方法/** 有多少行数据 */- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{    return self.tgs.count;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{    // 奇数cell显示TgCell,偶数行cell显示TestCell    if (indexPath.row % 2 == 0) {                ZYTgCell *cell = [tableView dequeueReusableCellWithIdentifier:tgID];        cell.tg = self.tgs[indexPath.row];        return cell;    }else{        ZYTestCell *cell = [tableView dequeueReusableCellWithIdentifier:testID];        return cell;    }            }@end

效果如下图: