iOS cell的复用以及自定义cell

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

文章目录

  • 自定义cell以及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;
@endNS_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复用的原理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/854074.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Fiddler抓包工具介绍

下载 下载:Web Debugging Proxy and Troubleshooting Tools|Fiddler 进去要填一个表 汉化版 百度网盘 请输入提取码 提取码&#xff1a;xq9t 下载过附件之后分别把两个文件 点开fiddler就ok了 配置https fiddler要想抓到https包(解密的),点击tools->options勾选三个对…

速盾:高防服务器防御 DDoS 攻击的掩护技巧

在当今互联网环境下&#xff0c;DDoS 攻击已成为网络安全的一大威胁&#xff0c;而高防服务器则是对抗这种攻击的重要手段。速盾作为提供高防服务器服务的品牌&#xff0c;在防御 DDoS 攻击方面有着独特的技巧和策略。 首先&#xff0c;速盾高防服务器采用了智能流量分析技术。…

总结之Docker(四)——镜像修改非ROOT用户权限后生成新镜像并发布

Docker拉去目标镜像 docker pull redis:6.2.5如果出现拉去过程超时&#xff0c;或者连接失败。 添加镜像加速器&#xff0c;以阿里云为例&#xff0c;阿里云目前推广提供镜像加速器&#xff0c;需要登录。 https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors 生成…

HMI(人机交互)应用的15大领域,欢迎补充。

HMI&#xff08;Human-Machine Interface&#xff0c;人机界面&#xff09;可以应用于许多不同的场景和行业&#xff0c;包括但不限于以下几个方面&#xff1a; 工业控制系统&#xff1a;HMI在工业生产中广泛应用&#xff0c;用于监控和控制生产过程。例如&#xff0c;工厂中的…

【OS】相关知识点收集

1 页面置换 页面置换算法是在计算机内存管理中用于决定哪些页面应该被替换出内存&#xff0c;以便为新的页面腾出空间的策略。以下是关于页面置换算法的详细回答&#xff0c;参考了多篇相关文章的信息。 1. 页面置换算法概述 页面置换算法主要应用于在存储体系当中&#xff…

NewStarCTF_RE(week1,2)

[NewStarCTF 2023 公开赛道]easy_RE ida 可能会把 一个数组或字符串拆开&#xff0c;可以通过计算地址&#xff0c;知道是一起的 也有的会藏在汇编窗口 Segments IDA的Segments窗口 &#xff1a;shiftf7 https://www.cnblogs.com/sch01ar/p/9477697.html ida 各种窗口也是需要…

技术周总结2024.06.10~06.16(AI Agent,Maven, Idea)

文章目录 一、06.14 周五1.1&#xff09;问题01&#xff1a;常见的 maven命令都有哪些&#xff0c;都怎么使用1. mvn clean2. mvn compile3. mvn test4. mvn package5. mvn install6. mvn deploy7. mvn clean install8. mvn dependency:tree9. mvn site10. mvn exec:java11. mv…

AMD平台,5600X+6650XT,虚拟机安装macOS 14(2024年6月)

AMD平台安装macOS 14的麻烦&#xff0c;要比Intel平台多的多&#xff0c;由于macOS从13开始&#xff0c;对CPU寄存器的读取进行了改变&#xff0c;导致AMD平台只要安装完macOS 13及以后版本&#xff0c;开机后就报五国语言错误&#xff0c;不断重启。改vmx文件&#xff0c;被证…

mongodb command

1. start and stop ./mongod --dbpath -dbpath /data/shard1/db --logpath -dbpath /data/shard1/db/logs/mongodb.log --fork mongod --shutdown --dbpath /data/shard1/db MongoDB基础篇-03-启动与关闭_mongodb启动和关闭-CSDN博客 2. 查看分片数据分布 mongo mongo01.c…

用React编写一个密码组件表单

theme: condensed-night-purple highlight: atelier-cave-light 背景介绍 我们在使用网站或者应用程序的登录界面或创建帐户界面时&#xff0c;往往避免不了需要用户输入密码这一步骤&#xff0c;而用户是否可以选择看见他们输入的密码是十分重要的一项功能。尤其是在当输入的…

Java面向对象-final关键字

Java面向对象-final关键字 一、final1、修饰变量2、修饰方法3、修饰类4、案例 一、final 可以修饰变量、方法、类 1、修饰变量 final修饰一个变量&#xff0c;变量的值不可以改变&#xff0c;这个变量就变成一个字符常量&#xff0c;约定俗称的规定&#xff1a;名字大写。 f…

大数据开发语言Scala入门 ,如何入门?

Ai文章推荐 1 作为程序员&#xff0c;开发用过最好用的AI工具有哪些&#xff1f; 2 Github Copilot正版的激活成功&#xff0c;终于可以chat了 3 idea,pycharm等的ai assistant已成功激活 4 新手如何拿捏 Github Copilot AI助手&#xff0c;帮助你提高写代码效率 5 Jetbrains的…

kotlin 中的字符

一、字符类型 1、kotlin中&#xff0c;字符用Char类型表示&#xff0c;值使用单引号 括起来。 fun main() {val a: Char 1println(a) // 1println("a类型为&#xff1a;${a.javaClass.simpleName}") // a类型为&#xff1a;char } 2、特殊字符的表示。 \t——制…

改进YOLO系列 | CVPR 2021 | Involution:超越convolution和self-attention的神经网络算子

Involution&#xff1a;超越卷积和自注意力的新型神经网络算子&#xff08;中文综述&#xff09; 简介 Involuton是CVPR 2021上提出的新型神经网络算子&#xff0c;旨在超越卷积和自注意力&#xff0c;提供更高效、更具表达力的特征提取能力。 Involution原理 Involution的…

【flink实战】flink-connector-mysql-cdc导致mysql连接器报类型转换错误

文章目录 一. 报错现象二. 方案二&#xff1a;重新编译打包flink-connector-cdc1. 排查脚本2. 重新编译打包flink-sql-connector-mysql-cdc-2.4.0.jar3. 测试flink环境 三. 方案一&#xff1a;改造flink连接器 一. 报错现象 flink sql任务是&#xff1a;mysql到hdfs的离线任务&…

IPTCP知识

1. IP&#xff1a; IP地址是一个32位的二进制数&#xff0c;通常被分割为4个“8位二进制数”IP地址分类&#xff1a;A类地址、B类地址、C类地址、D类地址、E类地址 A类地址分配给规模特别大的网络使用&#xff0c;B类地址分配给一般的中型网络&#xff0c;C类地址分配给小型网…

短URL服务设计

引言 在营销系统里&#xff0c;为了增加系统的活跃用户数&#xff0c;经常会有各种各样的营销活动。这类活动几乎都是为了充分利用存量用户的价值&#xff0c;促使他们分享产品或App以达到触达到更多用户的目的。又或者是出于营销目的&#xff0c;群发优惠券触达短信这种场景。…

Kotlin 数据类(Data Class)

Kotlin 数据类&#xff08;Data Class&#xff09;是一种特别用于持有数据的类。它们简化了数据类的创建&#xff0c;并提供了一些自动生成的方法。下面详细介绍 Kotlin 数据类的原理和使用方法。 数据类的定义 Kotlin 中的数据类使用 data 关键字定义。例如&#xff1a; da…

MVC 框架安全

在现代 Web 开发中&#xff0c;使用 MVC 架构是一种流行的做法。MVC 是 Model-View-Controller 的缩写&#xff0c;它将 Web 应用分为三层&#xff0c;View 层负责用户视图、页面展示等工作&#xff1b;Controller 负责应 用的逻辑实现&#xff0c;接收 View 层传入的用户请求&…

016基于SSM+Jsp的医院远程诊断系统

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…