UITableViewCell创建方式和重用

UITableViewCell
•UITableView的每一行都是一个UITableViewCell,通过dataSource的tableView:cellForRowAtIndexPath:方法来初始化每一行
•UITableViewCell是UIView的子类,内部有个默认的子视图:contentView。contentView是UITableViewCell显示内容的父视图,并负责显示一些辅助指示视图。辅助指示视图的作用是显示一个表示动作的图标,可以通过设置UITableViewCell的accessoryType来显示,默认是UITableViewCellAccessoryNone,即不显示辅助指示视图 ,其他值如下:
•UITableViewCellAccessoryDisclosureIndicator
•UITableViewCellAccessoryDetailDisclosureButton
•UITableViewCellAccessoryCheckmark
 
UITableViewCell——contentView
•contentView下默认有3个子视图,其中的2个是UILabel,通过textLabel和detailTextLabel属性访问,第3个是UIImageView,通过imageView属性访问
•UITableViewCell的UITableViewCellStyle,用于决定使用contentView的哪些子视图,以及这些子视图在contentView中的位置,对应样式如下
 

UITableViewCell的创建方式

方式1 直接通过alloc:

//返回当前行显示的cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"cellForRowAtIndexPath-%ld-%ld",indexPath.section,indexPath.row);

    UITableViewCell *cell = [[UITableViewCell alloc] init];
    
    if (indexPath.section == 0) {
        //第一组
        if (indexPath.row == 0) {
            //第一组  第一行
            cell.textLabel.text = @"张三";
        }else if(indexPath.row == 1){
            //第一组  第2行
            cell.textLabel.text = @"李四";
        }else{
            //第一组  第3行
            cell.textLabel.text = @"王五";
        }
    }else{
        //第二组
        if(indexPath.row == 0){
            cell.textLabel.text = @"刘德华";
        }else{
            cell.textLabel.text = @"张学友";
        }
    }

    return cell;
}

   

方式2 通过tableView的静态单元格方式,此方式只是静态的,固定的行:

  

这样就可以实现静态表格内容

 

方式3 通过xib方式(经测试,此方式xib中一定记得identifier需要设置可重用的标识Id,如果为空又没有手动register注册,那么cell不会循环利用):

  

//返回每行显示的cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //1 创建可重用的cell
    static NSString *reuseId = @"gb";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId];
    if (cell == nil) {
//        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseId];
        //从xib中加载cell
        cell = [[[NSBundle mainBundle] loadNibNamed:@"CZGroupBuyingCell" owner:nil options:nil] lastObject];
        
        //从xib中加载view的另一种方式
//        UINib *nib = [UINib nibWithNibName:@"CZGroupBuyingCell" bundle:nil];
//        cell = [[nib instantiateWithOwner:nil options:nil] lastObject];
    }

    //2 设置cell内部的子控件
    //2.1 获取当前要展示的数据
    CZGroupBuying *gb = self.groupBuyings[indexPath.row];
    //2.2 设置值
//    cell.textLabel.text = gb.title;
//    cell.detailTextLabel.text = [NSString stringWithFormat:@"¥%@",gb.price];
//    cell.imageView.image = [UIImage imageNamed:gb.icon];
    
    
    UILabel *titleView = (UILabel *)[cell viewWithTag:10];
    titleView.text = gb.title;
    
    //3 返回
    return cell;
}

 

自定义cell

 

定义cell中放入的控件,自动归为Cell的content view视图的子视图

@class CZGroupBuying;

@interface CZGroupBuyingCell : UITableViewCell
@property (nonatomic, strong) CZGroupBuying *groupBuying;

+ (instancetype)groupBuyingCellWithTableView:(UITableView *)tableView;
@end

 

@interface CZGroupBuyingCell ()
@property (weak, nonatomic) IBOutlet UIImageView *iconView;
@property (weak, nonatomic) IBOutlet UILabel *titleView;
@property (weak, nonatomic) IBOutlet UILabel *priceView;
@property (weak, nonatomic) IBOutlet UILabel *buyCountView;

@end

@implementation CZGroupBuyingCell
//创建自定义可重用的cell对象
+ (instancetype)groupBuyingCellWithTableView:(UITableView *)tableView
{
    static NSString *reuseId = @"gb";
    CZGroupBuyingCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId];
    if (cell == nil) {
        cell = [[[NSBundle mainBundle] loadNibNamed:@"CZGroupBuyingCell" owner:nil options:nil] lastObject];
    }
    return cell;
}

//重写属性的setter方法,给子控件赋值
- (void)setGroupBuying:(CZGroupBuying *)groupBuying
{
    _groupBuying = groupBuying;
    
    self.titleView.text = groupBuying.title;
    self.priceView.text = [NSString stringWithFormat:@"¥ %@",groupBuying.price];
    self.buyCountView.text = [NSString stringWithFormat:@"%@人已购买",groupBuying.buyCount];
    self.iconView.image = [UIImage imageNamed:groupBuying.icon];
}
#warning 先从换成池中取,如果缓存池中没有可循环利用的cell,先去storyboard或xib中找合适的cell ,cell是从xib中创建出来的,而不是手写代码方式alloc出来的

  static NSString *reuseId = @"gb";
    CZGroupBuyingCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId];
从xib或storyboard中创建的cell,创建完毕后系统会调用awakeFromNib方法
/**
 *  如果cell是通过storyboard或者xib创建的,就会调用这个方法来初始化cell
 *  这个方法的作用类似于init方法
 */
- (void)awakeFromNib {
    NSLog(@"%s",__func__);
    // Initialization code
    // 自定义表格分割线
    UIView *separatorView = [[UIView alloc] init];
#warning 添加至cell的内容视图中
    [self.contentView addSubview:separatorView];
    
    self.separatorView = separatorView;
    
    separatorView.alpha = 0.5;
    separatorView.backgroundColor = [UIColor redColor];
    
}
不会调用initwithStyle方法 - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{

  在获取cell使用创建和赋值操作

//返回每行显示的cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //1 创建可重用的自定义的cell
    CZGroupBuyingCell *cell = [CZGroupBuyingCell groupBuyingCellWithTableView:tableView];
    
    //2 设置cell内部的子控件
    CZGroupBuying *gb = self.groupBuyings[indexPath.row];
    cell.groupBuying = gb;
    //3 返回
    return cell;
}

 

方式4 通过storyboard 通过此方式一般是使用tableview的动态原型功能:

  

  

  获取storyboard中cell的方式

+ (instancetype)tableViewCell:(UITableView *)tableView{
#warning 先从换成池中取,如果缓存池中没有可循环利用的cell,先去storyboard中找合适的cell ,cell是从storyboard中创建出来的,而不是手写代码方式alloc出来的
    // 此标识要和storyboard 本控制器中的动态cell设置的identify标识一致
    static NSString *ID = @"contactCell";
    return [tableView dequeueReusableCellWithIdentifier:ID];
}

 通过tableview dequeueReusableCellWithIdentifier:ID 系统就会去storyboard中找合适的cell

/**
 *  如果cell是通过storyboard或者xib创建的,就会调用这个方法来初始化cell
 *  这个方法的作用类似于init方法
 */
- (void)awakeFromNib {
    NSLog(@"%s",__func__);
    // Initialization code
    // 自定义表格分割线
    UIView *separatorView = [[UIView alloc] init];
#warning 添加至cell的内容视图中
    [self.contentView addSubview:separatorView];
    
    self.separatorView = separatorView;
    
    separatorView.alpha = 0.5;
    separatorView.backgroundColor = [UIColor redColor];
    
}
 
UITableViewCell对象的重用原理
•iOS设备的内存有限,如果用UITableView显示成千上万条数据,就需要成千上万个UITableViewCell对象的话,那将会耗尽iOS设备的内存。要解决该问题,需要重用UITableViewCell对象
•重用原理:当滚动列表时,部分UITableViewCell会移出窗口,UITableView会将窗口外的UITableViewCell放入一个对象池中,等待重用。当UITableView要求dataSource返回UITableViewCell时,dataSource会先查看这个对象池,如果池中有未使用的UITableViewCell,dataSource会用新的数据配置这个UITableViewCell,然后返回给UITableView,重新显示到窗口中,从而避免创建新对象
 
•还有一个非常重要的问题:有时候需要自定义UITableViewCell(用一个子类继承UITableViewCell),而且每一行用的不一定是同一种UITableViewCell(如短信聊天布局),所以一个UITableView可能拥有不同类型的UITableViewCell,对象池中也会有很多不同类型的UITableViewCell,那么UITableView在重用UITableViewCell时可能会得到错误类型的UITableViewCell
•解决方案:UITableViewCell有个NSString *reuseIdentifier属性,可以在初始化UITableViewCell的时候传入一个特定的字符串标识来设置reuseIdentifier(一般用UITableViewCell的类名)。当UITableView要求dataSource返回UITableViewCell时,先通过一个字符串标识到对象池中查找对应类型的UITableViewCell对象,如果有,就重用,如果没有,就传入这个字符串标识来初始化一个UITableViewCell对象
 
关于UITableView性能优化使用的提示
1.创建UITableViewCell时,必须设置一个唯一标示
2.去缓存池取出UITableViewCell时,必须传入一个标示
 
UITableViewCell重用,通过tableview dequeueReusableCellWithIdentifier:ID 系统就会去storyboard中找合适的cell
 

[[[NSBundle mainBundle] loadNibNamed:@"TableViewCellBase" owner:nil options:nil] lastObject],通过代码方式加载xib,如果cellBasexib中设置了Identifier,那么系统创建cell后还会把这个cell放入缓存池中

所以一下代码是会循环利用:

 

通过xib方式创建cell:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
     // cell会循环利用
    TableViewCellBase *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    if(!cell){
        NSLog(@"cell is nil");
        cell = [[[NSBundle mainBundle] loadNibNamed:@"TableViewCellBase" owner:nil options:nil] lastObject]; // 通过xib方式创建cell,如果xib中的identifier设置的重用标识,那么新创建出来的cell系统会添加至缓存中
    }
    cell.timeLabel.text = [NSString stringWithFormat:@"%ld",indexPath.row];
    
    NSLog(@"%p",cell);
    
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    
    
    return cell;
}

 

通过代码方式创建cell:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    
    // 会循环利用
    TableViewCellBase *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    if(!cell){
        NSLog(@"cell is nil");
         cell = [[TableViewCellBase alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID]; // 通过代码方式创建cell,并且传入cell重用标识,那么新创建出来的cell系统会添加至缓存中
    }
    
    cell.timeLabel.text = [NSString stringWithFormat:@"%ld",indexPath.row];
    
    NSLog(@"%p",cell);
    
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    
    return cell;
}

 

通过注册cell方式:

[self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([TableViewCellBase class]) bundle:nil] forCellReuseIdentifier:cellID]; // 手动把cell注册进入系统缓存中

 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
     // cell会循环利用
    TableViewCellBase *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; // 直接从系统缓存中取,因为已经手动注册了
    
    cell.timeLabel.text = [NSString stringWithFormat:@"%ld",indexPath.row];
    
    NSLog(@"%p",cell);
    
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    
    
    return cell;
}

  

 

 

 

 

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/HJiang/p/4197123.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值