iOS cell的复用以及自定义cell

自定义cell以及cell复用的内容

前言

cell是我们开发中的一个重要的控件,下面来讲解一下这个内容

cell的复用原理

cell的复用是UITableView的最核心的内容,这里解释一下他的一个复用原理:

初始化的时候他会先创建cell的缓存字典 和 section的缓存array,以及一个用于存放复用cell的mutableSet(可变的集合)。并且它会去创建显示的(n+1)个cell,其他都是从中取出来重用。

当有cell滑出屏幕时,会将其放入到一个set中(相当于一个重用池),当UITableView要求返回cell的时候,datasource会先在集合中查找是否有闲置的cell,若有则会将数据配置到这个cell中,并将cell返回给UITabelView。 这大大减少了内存的开销。

因为我在滚动的过程中会出现一个将cell滚出屏幕外的时候,这时候如果我们一直创建cell的话,如果cell太多了就会出现一个内存开销过多的一个问题。所以我们要采用这个复用的方式来提高内存利用率。

在表视图显示的时候,会创建(视图中可看的单元格个数+1)个单元格,一旦单元格因为滑动的而消失在我们的视野中的时候,消失的单元格就会进入缓存池(或叫复用池),当有新的单元格需要显示的时候,会先从缓存池中取可用的单元格,获取成功则使用获取到的单元格,获取失败则重新创建新的单元格,这就是整个的复用机制。

cell的复用的两种不同方式

接下来讲一下·cell的两种复用方式,主要分成注册和非注册两种方式。

注册

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tableView = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStyleGrouped];
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    self.ary = @[@"头像", @"名字", @"微信号"];
    [self.view addSubview:_tableView];
    [self.tableView registerClass:[cell02 class] forCellReuseIdentifier:@"cell"]; //使用代码自定义cell
    // Do any additional setup after loading the view.
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    cell02* cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
    return cell;
}

非注册

- (void)viewDidLoad {
    [super viewDidLoad];
    _tableView = [[UITableView alloc] initWithFrame:self.view.bounds style: UITableViewStyleGrouped];
    //设置两个代理
    _tableView.delegate = self;
    _tableView.dataSource = self;
    [self.view addSubview:_tableView];
    // Do any additional setup after loading the view.
}
-(UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString* cellStr = @"cell";
    UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:cellStr];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellStr];
    }
    return cell;
    

这两种方式都是可以实现复用的,两者有部分的区别,这里引用一段学长博客的话:

上述代码的区别在于注册方法需要提前对我们要使用的cell类进行注册,如此一来就不需要在后续过程中对我们的单元格进行判空。
这是因为我们的注册方法:

  • (void)registerClass:(nullable Class)cellClass forCellReuseIdentifier:(NSString *)identifier API_AVAILABLE(ios(6.0));
    在调用过程中会自动返回一个单元格实例,如此一来我们就避免了判空操作

区别2:

引用的方法不同

  • - (nullable __kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier;
  • (__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0);

前者用于非注册的方式,后者用于注册的方式中。在写代码的时候注意一一对应。

自定义cell的实现

我们首先要实现自定义cell需要实现两个协议:

UITableViewDelegateUITableViewDataSource

前者的主要用于实现显示单元格,设置单元格的行高和对于制定的单元格的操作设置头视图和尾视图。

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section API_AVAILABLE(ios(6.0));
- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section API_AVAILABLE(ios(6.0));
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath API_AVAILABLE(ios(6.0));
- (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section API_AVAILABLE(ios(6.0));
- (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section API_AVAILABLE(ios(6.0));
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;

后者主要用于设置UITableView的section和row的数量

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;

// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

我们的UIVIewContorller中要实现上面的部分协议函数,后面就是我们有关自定义cell的核心部分,就是我们的自定义的cell的类的部分。
我们自定义cell先要创建一个类继承UITableViewCell

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN
@interface myCustomCell : UITableViewCell  //在这里设置我们自己需要的一些UI控件
@property (nonatomic, strong) UIButton* btn;
@property (nonatomic, strong) UILabel* label1;
@property (nonatomic, strong) UILabel* label2;
@property (nonatomic, strong) UIImageView* imageView01;
@end

NS_ASSUME_NONNULL_END

然后需要重写一个方法- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier

-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];

    if ([self.reuseIdentifier isEqualToString:@"picture"]) {
        _label1 = [[UILabel alloc] init];
        _label1.textColor = UIColor.blackColor;
        _label1.font = [UIFont systemFontOfSize:17];
        [self.contentView addSubview:_label1];
        
        _label2 = [[UILabel alloc] init];
        _label2.textColor = UIColor.grayColor;
        _label2.font = [UIFont systemFontOfSize:10];
        [self.contentView addSubview:_label2];
        
        _imageView01 = [[UIImageView alloc] init]; // 创建UIImageView对象
        [self.contentView addSubview:_imageView01];
        
        _btn = [UIButton buttonWithType:UIButtonTypeCustom];
        [self.contentView addSubview:_btn];
    }
    return self;
}

最后设置一个布局

-(void)layoutSubviews {
    //设置一下自己ui控件的frame
}

这样就可以实现我们的一个自定义cell的内容了。

总结

这里简单介绍了一下有关自定义cell的内容和cell复用的原理。

  • 13
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值