cell的复用机制和自定义cell

cell的复用机制和自定义cell

UITableView

在学习cell之前,我们需要先了解UITableViewUITableView继承于UIScrollView,拥有两个两个相关协议

UITableViewDelegateUITableViewDataSource,前者用于显示单元格,设置行高以及对单元格进行指定操作,插入头视图和脚视图,后者用于设置TableView的section和row的数量(section相当于行,row相当于列)。

cell的复用方式

非注册

使用非注册方法,对cell类进行注册,我们需要对cell进行判空

  • 非注册方式是直接通过实例化单元格对象,并在需要时手动创建和配置每个单元格。
  • 这种方式通常在简单的表格或特殊情况下使用,不需要频繁的单元格重用。
  • 使用非注册方式时,可以通过实例方法 UITableViewCell(style:reuseIdentifier:) 或其他自定义初始化方法来创建单元格对象。
  • 每次需要显示新的单元格时,都会实时创建新的单元格对象,而不会尝试重用已存在的单元格。
  • 非注册方式的优点是简单直接,适用于一些简单的表格或特殊的使用情况。
- (void)viewDidLoad
{[super viewDidLoad];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{static NSString *identifier = @"mycell";UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];if (!cell) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];}// Configure the cell......return cell;
}

注册

  • 注册单元格是通过调用 UITableView 的 register(_:forCellReuseIdentifier:) 方法来完成的。通常在 viewDidLoad 或类似的初始化方法中执行。

  • 在注册单元格时,您需要提供一个标识符(ReuseIdentifier),用于标识特定类型的单元格。

  • 当需要创建新的单元格时,UITableView 会使用注册的标识符来实例化单元格对象,并自动管理单元格的重用。

  • 每次调用 dequeueReusableCell(withIdentifier:for:) 方法获取单元格时,UITableView 都会尝试从重用池中获取已注册的单元格,如果池中没有可重用的单元格,则根据注册信息创建新的单元格。

  • 注册单元格的好处是可以提高性能,因为它使 UITableView 能够有效地管理单元格的重用和内存占用,从而避免不必要的创建和销毁。

- (void)viewDidLoad 
{[super viewDidLoad];// 如果使用代码自定义 Cell[self.tableView registerClass:[CustomCell class] forCellReuseIdentifier:@"myCell"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{static NSString *identifier = @"mycell";UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];// Configure the cell......return cell;
}

区别

  1. 使用注册方法在程序的实现之中不需要进行判空操作,是因为已经在初始化阶段对需要使用的cell类进行注册,所以就可以免去判空的操作
  2. 我们可以注意到在获取 Cell 时,两种方式调用了不同的 method,dequeueReusableCellWithIdentifier:identifier第一个 method 用在了非注册的方式里,equeueReusableCellWithIdentifier:identifier forIndexPath:indexPath第二个 method 用在了需要注册的方式里。

cell的复用原理

cell的复用原理是使用三个容器进行实现

  1. Cell的缓存字典和Section的缓存Array:
    • 为了提高复用性能,可以使用缓存字典和缓存数组来存储已创建的 UITableViewCell 实例。
    • 缓存字典的键是重用标识符,值是一个数组,每个元素都是具有相同重用标识符的可复用单元格实例。
    • 缓存数组用于缓存每个 section 中的单元格数据,使得访问和管理每个 section 的单元格更加方便。
  2. 可复用集合(Mutable Set):
    • 可复用集合是一个可变的集合(如 NSMutableSet),用于存放当前可复用的 UITableViewCell 实例。
    • 当单元格滚动离开屏幕时,它会被添加到可复用集合中,以备后续的复用。
    • 当需要获取可复用的单元格时,首先从可复用集合中检查是否有可用的单元格实例。

这个可复用的集合其实就是我们所说的复用池,也称之为_reusableCells:

关于cell的复用

单元格在显示的时候就会创建视图中可看到的单元格数+ 1的单元格。在UITableView滚动的过程中,会使用复用机制进行对单元格对象的管理,避免了频繁创建和销毁单元格,以达到提高性能和内存的利用率。当某个单元格离开屏幕范围时,它会被回收并放入_reusableCells集合中,等待被重复使用。当新的单元格需要显示时,UITableView会首先尝试从_reusableCells中获取一个可复用的单元格对象,如果_reusableCells中没有可用的单元格,则会通过实例化新的UITableViewCell对象来满足需求。

即通俗的来说,当滑动的等操作使原本在屏幕上的cell不显示在屏幕上,就会将移除到单元格中的复用池之中,然后再加载新的cell的时候也并不是新创建一个cell,而是直接从对象池中取出一个cell对象,然后给它的相关属性赋上新的值,从而实现cell的复用。

自定义cell

由于系统给出的cell只能够实现文字,所有时候我们就需要使用自定cell,来生成我们想要的单元格格式

自定义cell的实现需要以下步骤

  1. 创建 UITableViewCell 的子类
  2. 定义 UITableViewCell 的界面和布局
  3. 注册和使用自定义 UITableViewCell

步骤一:

#import <UIKit/UIKit.h>NS_ASSUME_NONNULL_BEGIN@interface JCTableViewCell : UITableViewCell@property (nonatomic, strong) UILabel *label;
@property (nonatomic, strong) UIButton *button;@endNS_ASSUME_NONNULL_END

步骤二:

#import "JCTableViewCell.h"@implementation JCTableViewCell- (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
}- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];self.label = [[UILabel alloc] init];self.label.text = @"子视图";self.label.backgroundColor = [UIColor redColor];[self.contentView addSubview:_label];self.button = [UIButton buttonWithType:UIButtonTypeRoundedRect];[self.button setTitle:@"按钮" forState:UIControlStateNormal];[self.button addTarget:self action:@selector(buttonTapped) forControlEvents:UIControlEventTouchUpInside];[self.contentView addSubview:self.button];return self;
}- (void)layoutSubviews {[super layoutSubviews];self.label.frame = CGRectMake(0, 0, 70, 80);self.button.frame = CGRectMake(100, 0, 70, 70);
}- (void)buttonTapped {// 在此处理按钮点击事件NSLog(@"按钮被点击");
}@end

步骤三:

#import "ViewController.h"
#import "JCTableViewCell.h"
@interface ViewController ()@endstatic NSString *str = @"id";
@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];self.view.backgroundColor = [UIColor redColor];tview = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];tview.delegate = self;tview.dataSource = self;tview.backgroundColor = [UIColor grayColor];[tview registerClass:[JCTableViewCell class] forCellReuseIdentifier:str];[self.view addSubview:tview];
}- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {return 80.0; // 设置为适当的单元格高度
}- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{return 5;
}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {JCTableViewCell *cell = [tview dequeueReusableCellWithIdentifier:str];return cell;
}
@end

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

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

相关文章

Java从入门到放弃

线程池的主要作用 线程池的设计主要是为了管理线程&#xff0c;为了让用户不需要再关系线程的创建和销毁&#xff0c;只需要使用线程池中的线程即可。 同时线程池的出现也为性能的提升做出了很多贡献&#xff1a; 降低了资源的消耗&#xff1a;不会频繁的创建、销毁线程&…

LeetCode 算法:缺失的第一个正数c++

原题链接&#x1f517;&#xff1a;缺失的第一个正数 难度&#xff1a;困难⭐️⭐️⭐️ 题目 给你一个未排序的整数数组 nums &#xff0c;请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1&#xff1a; 输…

(第31天)【leetcode题解】404、左叶子之和

目录 404、左叶子之和题目描述思路代码 404、左叶子之和 题目描述 给定二叉树的根节点 root &#xff0c;返回所有左叶子之和。 思路 题目分析&#xff1a; 判断左叶子节点&#xff1a;A节点的左孩子不为空&#xff0c;且左孩子的左右孩子都为空&#xff0c;那么这个左孩子…

Java手写HashMap

之前面试拼多多的时候问到了&#xff0c;但是没练习过。 直接上代码 import java.util.Objects;/*** ClassName: MyHashMap* PackageName: com.joshua* author: Joshua Lee* create: 2024/6/10 - 20:21* description: 自己实现HashMap*/ public class MyHashMap<K, V> {…

ASP.NET的WebService跨域CORS问题解决方案

ASP.NET WebService 跨域(CORS, Cross-Origin Resource Sharing)问题通常发生在当您尝试从不同的源(域名、协议或端口)调用 WebService 时。浏览器由于安全原因,默认会阻止此类跨域请求。为了解决这个问题,您需要在 WebService 服务器端配置 CORS。 以下是在 ASP.NET We…

域内攻击 ----> DCSync

其实严格意义上来说DCSync这个技术&#xff0c;并不是一种横向得技术&#xff0c;而是更偏向于权限维持吧&#xff01; 但是其实也是可以用来横向&#xff08;配合NTLM Realy&#xff09;&#xff0c;如果不牵强说得话&#xff01; 那么下面&#xff0c;我们就来看看这个DCSyn…

[Vue3:axios]:实现登录跳转页面展示列表(查看教师所承担课程的学生选课情况)

文章目录 一&#xff1a;前置操作项目结构&#xff1a; 二&#xff1a;登录页面主要流程说明运行截图前端代码Login.vue 三&#xff1a;列表页面交互逻辑&#xff1a;涉及页面Page02.vue &#xff08;登录成功跳转学生选课页面&#xff09;运行截图 一&#xff1a;前置操作 ht…

数据结构:插入排序和希尔排序

插入排序 逆序的情况下&#xff1a; 时间复杂度&#xff1a;O(N^2) 空间复杂度&#xff1a;O(1) 顺序的情况下&#xff1a; 时间复杂度&#xff1a;O(N) 空间复杂度…

将字符串str1复制为字符串str2

定义两个字符数组str1和str2&#xff0c;再设两个指针变量p1和p2&#xff0c;分别指向两个字符数组中的有关字符&#xff0c;通过改变指针变量的值使它们指向字符串中的不同的字符&#xff0c;以实现字符的复制。编写程序&#xff1a; 运行程序&#xff1a; 程序分析&#xff1…

【T3】畅捷通T3软件查询明细账等账簿,出现某些列串位置。

【问题描述】 查询畅捷通T3软件科目明细账的时候&#xff0c; 出现某些行的数据串位置&#xff0c; 摘要、金额、方向都没有在对应的列。 【解决方案】 根据跟踪发现&#xff0c;最终在客户档案上发现问题。 数据串位中对应的客户名称、简称中的对后面多了一个【tab】键的空格…

从数组和指针笔试题深度理解 sizeof 和 strlen

一、sizeof 和 strlen 的区别 a.sizeof sizeof 计算变量所占内存内存空间大小的&#xff0c;单位是字节&#xff0c;如果操作数是类型的话&#xff0c;计算的是使用类型创建的变量所占内存空间的大小。sizeof 只关注占用内存空间的大小&#xff0c;不在乎内存中存放什么数据。…

Mysql学习(八)——多表查询

文章目录 五、多表查询5.1 多表关系5.2 多表查询概述5.3 内连接5.4 外连接5.5 自连接5.6 联合查询5.7子查询5.8 总结 五、多表查询 5.1 多表关系 概述&#xff1a;项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;…

Deepin安装PostGresql

最近要把开发环境完全从Windows移到Deepin上&#xff0c;本次介绍在Deepin借助apt-get安装和配置数据库。同时可以用Dbever提供图形化管理工具。 安装PostGreSQL数据库和创建数据库 #安装postgresql zhanglianzhuzhanglianzhu-PC:/$ sudo apt-get install postgresql-16 正在…

STM32CubeIDE使用过程记录

最近在做一款机器人的开发&#xff0c;使用到了STM32CubeIDE&#xff0c;这里记录一些使用技巧方便后续查阅。 STM32CubeIDE使用过程记录 快捷键开启代码自动补全功能看门狗设置CRC设置IO口取反定时器设置 及 定时器中断外部中断GPIO配置STC15单片机GPIO模式配置片内闪存&#…

完美落地的自动化测试框架(pytest):智能生成?业务依赖?动态替换?报告构建?你来,这儿有!

前言 随着软件测试行业的快速发展&#xff0c;去测试化、全员测开化的趋势&#xff0c;技术测试已成为确保软件质量不可或缺的一环。 但对于许多没有代码基础或缺乏系统性自动化知识的测试人员来说&#xff0c;如何入手并实现高质量的自动化测试成为了一个挑战。 为此&#xff…

【Java01】Java 17中的switch

Java 17中的switch 1. 新式switch语句的格式 switch (expression) {case value1 -> 表达式、代码块;case value2, value3 -> 表达式、代码块;// ...default -> 表达式、代码块; }case后允许同时放置多个valuecase value后的冒号变箭头case后的代码块不需要breakcase…

element-plus ui的使用说明

Element Plus UI的使用说明如下&#xff1a; 1. 安装Element Plus 首先&#xff0c;确保你的项目是基于Vue 3的。你可以使用npm或yarn来安装Element Plus。 使用npm安装&#xff1a; npm install element-plus --save 使用yarn安装&#xff1a; yarn add element-plus 2…

第54集《摄大乘论》

讲大家打开《讲义》第一八0页&#xff1a; 戊二、广能引发(分二&#xff1a;己一十难行&#xff1b;己二四作业) 己一、十难行(分二&#xff1a;庚一略释十难释&#xff1b;庚二重释随觉难行) 庚一、略释十难释(分二&#xff1a;辛一标数&#xff1b;辛二列释) 我们这一科讲…

Vue 路由实现组件切换

Vue 路由实现组件切换 不会就问 qq3131015733 觉得讲得不好了&#xff0c;麻烦喷一下&#xff0c;感谢反馈。 下拉菜单乃个项目的地址&#xff1a;https://1024code.com/ide/rzaqrgx 文章目录 Vue 路由实现组件切换前置知识入门效果展示安装依赖文件目录代码Home.vue代码Abou…

C语言 图形化界面方式连接MySQL【C/C++】【图形化界面组件分享】

博客主页&#xff1a;花果山~程序猿-CSDN博客 文章分栏&#xff1a;MySQL之旅_花果山~程序猿的博客-CSDN博客 关注我一起学习&#xff0c;一起进步&#xff0c;一起探索编程的无限可能吧&#xff01;让我们一起努力&#xff0c;一起成长&#xff01; 目录 一.配置开发环境 二…