iOS基础控件--UITableView之自定义cell和cell的复用

26 篇文章 1 订阅

在上一篇文章中有下面一段代码:

cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];

这里创建cell的时候设置了一个系统style和一个identifier
这里的两个属性就是今天这篇文章的内容:自定义cell和cell复用。

自定义cell

在通常的开发中,系统默认的cell样式并不能满足设计需求,所以自定义cell样式就是很基本的操作。
下面来简单实现一个和微信通讯录类似的cell:下面是全部代码
CustomerCell.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface CustomerCell : UITableViewCell
//声明两个属性,用于给视图赋值
@property (nonatomic, copy)NSString *title;
@property (nonatomic, copy)UIImage *image;

@end

NS_ASSUME_NONNULL_END

CustomerCell.m

#import "CustomerCell.h"

@implementation CustomerCell
{
    //声明两个视图
    UILabel *titleLabel;
    UIImageView *iconView;
}

//重写init方法
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
    //调用父类init方法创建
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        //创建成功则t给cell添加需要的子视图
        titleLabel = [[UILabel alloc] init];
        [self.contentView addSubview:titleLabel];
        
        iconView = [[UIImageView alloc] init];
        [self.contentView addSubview:iconView];
    }
    
    return self;
}

//重写layoutSubviews方法,给视图设置位置大小
- (void)layoutSubviews{
    iconView.frame = CGRectMake(20, 5, 54, 54);
    iconView.layer.masksToBounds = YES;
    iconView.layer.cornerRadius = 4;
    titleLabel.frame = CGRectMake(80, 5, 100, 30);
}

- (void)setTitle:(NSString *)title{
    titleLabel.text = title;
}

- (void)setImage:(UIImage *)image{
    iconView.image = image;
}

- (void)awakeFromNib {
    [super awakeFromNib];
    // Initialization code
}

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

    // Configure the view for the selected state
}

@end

ViewController.m中调用

#import "ViewController.h"
#import "CustomerCell.h"

@interface ViewController ()<UITableViewDelegate, UITableViewDataSource>//添加协议
{
    //声明tableView和数据源
    UITableView *table;
    NSMutableArray *titleArray;
    NSMutableArray *imageArray;
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self createDataSource];
    [self createTableView];
}

//创建数据源
- (void)createDataSource{
    //初始化数据源数组
    titleArray = [NSMutableArray arrayWithCapacity:0];
    imageArray = [NSMutableArray arrayWithCapacity:0];
    //循环给数据源中添加元素
    for (int i = 0; i < 14; i++) {
        NSString *string = [NSString stringWithFormat:@"第%d行", i+1];
        [titleArray addObject:string];
        
        NSString *imageName = [NSString stringWithFormat:@"image_%.2d.jpg", i+1];
        UIImage *image = [UIImage imageNamed:imageName];
        [imageArray addObject:image];
    }
    //刷新视图
    [table reloadData];
}

//创建tableView视图
- (void)createTableView{
    //创建并设置位置大小和风格形式
    table = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
    //设置代理
    table.delegate = self;
    table.dataSource = self;
    //设置纵横滑块不显示
    table.showsVerticalScrollIndicator = NO;
    table.showsHorizontalScrollIndicator = NO;
    [self.view addSubview:table];
}

#define mark --UITableViewDelegate
//设置列表中每个元素的行高,在非动态行高的情况下设置固定值。动态行高的情况需要计算。
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return 64;
}

//设置列表中元素的个数  一般设置为数据源中元素的个数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return titleArray.count;
}

//创建tableView中的每一个cell,这里使用复用机制。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    CustomerCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    if (cell == nil) {
        cell = [[CustomerCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
    }
    cell.title = titleArray[indexPath.row];
    cell.image = imageArray[indexPath.row];
    
    return cell;
}

@end

cell复用

//创建tableView中的每一个cell,这里使用复用机制。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    CustomerCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    if (cell == nil) {
        cell = [[CustomerCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
    }
    cell.title = titleArray[indexPath.row];
    cell.image = imageArray[indexPath.row];
    
    return cell;
}

在上面的代码的解释是:调用代理方法创建并使用cell,在每次使用cell的时候先从复用池中去找Identifier为“cell”的cell,找到以后就使用,没有就创建一个新的。如下图:
复用池理解

cell的复用机制是复用池的使用,复用池的意思是创建的cell都在池中,每一个cell都有一个Identifier作为标记,在从复用池中取cell的时候会根据Identifier取出,当没有找到的时候才去创建,这样的方式会尽可能少的创建cell以达到优化内存的效果。
复用池的实现是一个字典数组,大致可以理解为:array = [@{@“cell”:cell1, @“Identifier”: @“cell”},@{@“cell”:cell2, @“Identifier”: @“cell”}…];

cell的复用虽然节约了内存,但是有时也会带来一些麻烦,比如在一个带有UITextField的cell上,当cell滚动时,前面输入到textView上的文字会因为复用的问题而消失。这是一个比较严重的问题。在下一篇文章中再去研究带有UITextField的cell如何避免cell复用而带来的问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值