【iOS】cell的复用以及自定义cell

【iOS】cell的复用以及自定义cell

文章目录

  • 【iOS】cell的复用以及自定义cell
    • 前言
    • cell的复用
      • 手动(非注册)
      • 自动(注册)
    • 自定义cell

前言

  1. cell的复用及自定义cell是UITableView或UICollectionView的一个重要优化机制,当用户滚动视图时,只有少量可见的cell会被创建与显示,暂时不可见的,都会缓存起来以备后面复用,这个机制主要是为了提高应用性能。(创建与销毁都是相对开销高的操作,通过复用cell,可以避免不必要的视图创建与销毁,从而提高应用的滚动性能)

UICollectionView = 更自由、更强大的“多列列表”控件,适合做复杂的网格/横滑页面,如相册等

  1. 自定义cell可以更好的控制cell的外观和行为,提高代码的可读与维护性,自定义cell的步骤主要有:创建自定义cell类(继承于UITableViewCell),添加UI元素(如标签,按钮等),设置cell的布局(即调整组数与行数或者位置),及在TableView中使用自定义Cell。

实际开发里,我们通常会结合使用cell复用与自定义cell,可以达到优化性能和满足特定需求的目的

cell的复用

cell复用的主要概念前面已经讲了,下面主要介绍其内容,cell的复用主要有两种方法,分为自动(注册)和手动复用(非注册),现在更推荐自动的方式。二者的主要区别在于是否注册复用标识符,以及使用了哪个方法来取cell。

手动(非注册)

不用注册 cell,而是自己判断是否有复用的 cell,如果没有就手动创建一个。

  1. 在 cellForRowAtIndexPath中使用 dequeueReusableCellWithIdentifier:

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellID"];
    

    这行代码会从复用池中拿出一个标识为 “cellID” 的 cell,如果有就复用,如果没有,返回 nil

  2. 判断cell是否是nil如果是就手动创建

    if (!cell) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cellID"];
    }
    

    这里你必须手动 alloc/init 一个 cell,否则返回的是空的,程序会崩溃

  3. 配置cell的内容

    cell.textLabel.text = [NSString stringWithFormat:@"第 %ld 行", indexPath.row];
    

代码示例:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {// 第一步:尝试从复用池取 cellUITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellID"];// 第二步:如果没有可复用的,就手动 new 一个if (!cell) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cellID"];}// 第三步:配置 cell 内容cell.textLabel.text = [NSString stringWithFormat:@"第 %ld 行", indexPath.row];return cell;
}

自动(注册)

只需要正确地设置复用标识符并在需要时请求复用的cell 主要步骤如下:

  1. 注册cell

    在使用 tableView 前(通常在 viewDidLoad 中),注册 cell 的类文件:

    [self.tableView registerClass:[MyTableViewCell class] forCellReuseIdentifier:@"cellID"];
    
  2. 在 cellForRowAtIndexPath中获取复用的 Cell 使用 dequeueReusableCellWithIdentifier:forIndexPath:获取 cell,无需手动判断 nil:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {// 自动复用,不用判断 cell 是否为nilMyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellID" forIndexPath:indexPath];return cell;
}

自定义cell

前面提到自定义cell是在开发iOS应用时常用的一种方式,可以更好的控制cell的外观和行为

一般来说要实现自定义cell需要先实现两个协议:UITableViewDelegate和 UITableViewDataSource

UITableViewDelegate这个协议主要用于实现显示单元格,设置单元格的行高和对于制定的单元格的操作设置头视图和尾视图。这个协议中没有必须完成的方法,里面的都是可选方法

有如下方法:

// Display customization- (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));// Variable height support- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;

UITableViewDataSource

有以下两个必须实现的方法:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
//返回指定分区的行数
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
//为指定索引路径(indexPath)创建并配置单元格。

除此之外还有很多可选的方法,举出主要的几个:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;            
//确定表格视图里分区(section)的数量。若你没有实现该方法,系统会默认返回 1 个分区。
- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; 
//为指定分区设置文本形式的头部标题。若不实现该方法,分区将没有头部标题。
- (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
//为指定分区设置文本形式的底部标题。若不实现该方法,分区将没有底部标题。- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;
//判断指定行是否可以进入编辑状态(如删除、插入等操作)。若不实现该方法,系统默认所有行都可以编辑。

自定义cell主要的步骤包括:

  1. 创建自定义cell类:首先,需要创建一个新的类,通常会继承自UITableViewCell或UICollectionViewCell
  2. 添加UI元素:在这个自定义cell类中,我们可以添加你需要的UI元素或者属性,如UILabel,UIImageView等。
  3. 实现初始化方法:在自定义cell类的初始化方法中,需要初始化我们添加的UI元素,并添加到cell的contentView上。
  4. 设置cell的布局:还需要在自定义cell类中设置UI元素的布局,可以使用自己设置的方法layout来进行自己的布局
  5. 在TableView中使用自定义cell:在TableView的tableView(_:cellForRowAt:)方法中,我们需要先通过复用标识符尝试获取一个可复用的cell,如果没有获取到,那么就创建一个新的自定义cell实例,并返回。

代码示例:

MyTableViewCell.h

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

MyTableViewCell.m

#import "MyTableViewCell.h"@implementation MyTableViewCell- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];if (self) {self.label = [[UILabel alloc] init];self.label.font = [UIFont systemFontOfSize:16];self.label.textColor = [UIColor blackColor];[self.contentView addSubview:self.label];self.button = [UIButton buttonWithType:UIButtonTypeSystem];[self.button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];[self.contentView addSubview:self.button];self.ImageView = [[UIImageView alloc] init];self.ImageView.contentMode = UIViewContentModeScaleAspectFit;self.ImageView.clipsToBounds = YES;[self.contentView addSubview: self.ImageView];}return self;
}- (void)layoutSubviews {[super layoutSubviews];self.ImageView.frame = CGRectMake(10, 10, 60, 60);self.label.frame = CGRectMake(80, 15, 200, 30);self.button.frame = CGRectMake(self.contentView.bounds.size.width - 80, 15, 60, 40);
}@end

ViewController.h

#import <UIKit/UIKit.h>@interface ViewController : UIViewController<UITableViewDelegate, UITableViewDataSource>@property (nonatomic, strong) UITableView *tableView;@end

ViewController.m

#import "ViewController.h"
#import "MyTableViewCell.h"static NSString *str = @"id";@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];self.tableView.delegate = self;self.tableView.dataSource = self;self.tableView.backgroundColor = [UIColor grayColor];[self.tableView registerClass:[MyTableViewCell class] forCellReuseIdentifier:str];[self.view addSubview:self.tableView];
}- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {return 4;
}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {switch (section) {case 0:return 2;case 1:return 4;case 2:return 1;case 3:return 3;default:return 0;}
}- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {return 80;
}- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:str forIndexPath:indexPath];cell.label.text = [NSString stringWithFormat:@"第 %ld 组 第 %ld 行", indexPath.section + 1, indexPath.row + 1];[cell.button setTitle:@"点击" forState:UIControlStateNormal];NSString *imageName = [NSString stringWithFormat: @"ima%lu.jpg", indexPath.section + 1];cell.ImageView.image = [UIImage imageNamed: imageName];return cell;
}@end

请添加图片描述

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

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

相关文章

深度学习之模型压缩三驾马车:基于ResNet18的模型剪枝实战(2)

前言 《深度学习之模型压缩三驾马车&#xff1a;基于ResNet18的模型剪枝实战&#xff08;1&#xff09;》里面我只是提到了对conv1层进行剪枝&#xff0c;只是为了验证这个剪枝的整个过程&#xff0c;但是后面也有提到&#xff1a;仅裁剪 conv1层的影响极大&#xff0c;原因如…

传输层协议:UDP

目录 1、概念 2、报文结构 3、核心特性 3.1 无连接 3.2 不可靠交付 3.3 面向数据报 3.4 轻量级&高效 3.5 支持广播和组播 4、典型应用场景 5、优缺点分析 6、与TCP的区别 1、概念 UDP&#xff08;User Datagram Protocol&#xff0c;用户数据报协议&#xff09…

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…

【汇编逆向系列】七、函数调用包含多个参数之浮点型- XMM0-3寄存器

目录 1. 汇编代码 1.1 debug编译 1.2 release编译 2. 汇编分析 2.1 浮点参数传递规则 2.2 栈帧rsp的变化时序 2.3 参数的访问逻辑 2.4 返回值XMM0寄存器 3. 汇编转化 3.1 Debug编译 3.2 Release 编译 3.3 C语言转化 1. 汇编代码 上一节介绍了整型的函数传参&#x…

华为云Flexus+DeepSeek征文 | 从零到一:用Flexus云服务打造低延迟联网搜索Agent

作者简介 我是摘星&#xff0c;一名专注于云计算和AI技术的开发者。本次通过华为云MaaS平台体验DeepSeek系列模型&#xff0c;将实际使用经验分享给大家&#xff0c;希望能帮助开发者快速掌握华为云AI服务的核心能力。 目录 作者简介 前言 1. 项目背景与技术选型 1.1 项目…

【多智能体】受木偶戏启发实现多智能体协作编排

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本专栏《人工智能》旨在记录最新的科研前沿&#xff0c;包括大模型、具身智能、智能体等相关领域&#xff0c;期待与你一同探索、学习、进步&#xff0c;一起卷起来叭&#xff…

Java八股文——Spring篇

文章目录 Java八股文专栏其它文章Java八股文——Spring篇SpringSpring的IoC和AOPSpring IoC实现机制Spring AOP实现机制 动态代理JDK ProxyCGLIBByteBuddy Spring框架中的单例Bean是线程安全的吗&#xff1f;什么是AOP&#xff0c;你们项目中有没有使用到AOPSpring中的事务是如…

NineData数据库DevOps功能全面支持百度智能云向量数据库 VectorDB,助力企业 AI 应用高效落地

NineData 的数据库 DevOps 解决方案已完成对百度智能云向量数据库 VectorDB 的全链路适配&#xff0c;成为国内首批提供 VectorDB 原生操作能力的服务商。此次合作聚焦 AI 开发核心场景&#xff0c;通过标准化 SQL 工作台与细粒度权限管控两大能力&#xff0c;助力企业安全高效…

开源技术驱动下的上市公司财务主数据管理实践

开源技术驱动下的上市公司财务主数据管理实践 —— 以人造板制造业为例 引言&#xff1a;财务主数据的战略价值与行业挑战 在资本市场监管日益严格与企业数字化转型的双重驱动下&#xff0c;财务主数据已成为上市公司财务治理的核心基础设施。对于人造板制造业而言&#xff0…

借助它,普转也能获得空转信息?

在生命科学研究领域&#xff0c;转录组技术是探索基因表达奥秘的有力工具&#xff0c;在疾病机制探索、生物发育进程解析等诸多方面取得了显著进展。然而&#xff0c;随着研究的深入&#xff0c;研究人员发现普通转录组只能提供整体样本中的基因表达水平信息&#xff0c;却无法…

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…

Java事务回滚详解

一、什么是事务回滚&#xff1f; 事务回滚指的是&#xff1a;当执行过程中发生异常时&#xff0c;之前对数据库所做的更改全部撤销&#xff0c;数据库状态恢复到事务开始前的状态。这是数据库“原子性”原则的体现。 二、Spring 中的 Transactional 默认行为 在 Spring 中&am…

云灾备数据复制技术研究

云灾备数据复制技术&#xff1a;数字时代的“安全气囊” 在当今信息化时代&#xff0c;数据就像城市的“生命线”&#xff0c;一旦中断&#xff0c;后果不堪设想。想象一下&#xff0c;如果政务系统突然崩溃&#xff0c;成千上万的市民服务将陷入瘫痪。这就是云灾备技术的重要…

如何处理Shopify主题的显示问题:实用排查与修复指南

在Shopify店铺运营过程中&#xff0c;主题显示问题是影响用户体验与品牌形象的常见痛点。可能是字体错位、图片无法加载、移动端显示混乱、功能失效等&#xff0c;这些都可能造成客户流失和转化下降。 本文将从问题识别、原因分析、修复方法到开发者建议全方位解读如何高效解决…

前端监控方案详解

一、前端监控方案是什么&#xff1f; 前端监控方案是一套系统化的工具和流程&#xff0c;用于收集、分析和报告网站或Web应用在前端运行时的各种性能指标、错误日志、用户行为等数据。它通常包括以下几个核心模块&#xff1a; 性能监控&#xff1a;页面加载时间、资源加载时间…

Camera相机人脸识别系列专题分析之十二:人脸特征检测FFD算法之libvega_face.so数据结构详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; Camera相机人脸识别系列专题分析之十一&#xff1a;人脸特征检测FFD算法之低功耗libvega_face.so人脸属性(年龄&#xff0c;性别&#xff0c;肤…

如何配置HarmonyOS 5与React Native的开发环境?

配置 HarmonyOS 5 与 React Native 的开发环境需遵循以下步骤 一、基础工具安装 ‌DevEco Studio 5.0‌ 从 HarmonyOS 开发者官网 下载安装勾选组件&#xff1a; HarmonyOS SDK (API 12)ArkTS 编译器JS/ArkTS 调试工具HarmonyOS 本地模拟器 ‌Node.js 18.17 # 安装后验证版…

kotlin kmp 副作用函数 effect

在 Kotlin Multiplatform (KMP) Compose 中&#xff0c;“effect functions”&#xff08;或“effect handlers”&#xff09;是专门的可组合函数&#xff0c;用于在 UI 中管理副作用。 在 Compose 中&#xff0c;可组合函数应该是“纯”的和声明式的。这意味着它们应该理想地…

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…