【iOS】自定义cell及其复用机制

2024-06-17 09:28
文章标签 自定义 ios 机制 复用 cell

本文主要是介绍【iOS】自定义cell及其复用机制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • cell的复用
    • 注册
    • 非注册
    • 两者的区别
  • 自定义cell

cell的复用

当用户滚动 UITableView 或 UICollectionView 时,只有少量可见的 cell 会被实际创建和显示。对于那些暂时不可见的 cell,系统会将它们缓存起来以备将来复用。这就是所谓的 cell 复用机制。

在这里插入图片描述

为什么需要cell的复用:

  • 提高性能: 不需要为每个 cell 都创建一个新的实例,减少了创建 cell 的开销,从而提高了滚动的流畅度。
  • 节省内存: 只维护少量可见 cell 的实例,而不是为整个数据集创建 cell,从而大大节省了内存使用。
  • 简化代码: 通过复用 cell,我们只需要更新 cell 的内容,而不需要频繁地创建和销毁 cell 实例。

实现cell的复用有两种方法,一种是手动判空实现,一种是使用cell的注册机制

注册

  • 注册单元格是在viewDidLoad中使用register(_:forCellReuseIdentifier:)方法来完成的
  • 在创建cell的函数中使用dequeueReusableCellWithIdentifier获取可复用的cell。(如果没有可复用的cell,就自动利用注册cell时提供的类创建一个新的cell并返回)

示例程序

- (void)viewDidLoad 
{[super viewDidLoad];// 使用代码自定义 Cell[self.tableView registerClass:[CustomCell class] forCellReuseIdentifier:@"id"];
}- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {static NSString *strID = @"id";MyTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier: strID];return cell;
}

非注册

  • 非注册方法是直接通过实例化单元格对象,并在需要时手动创建和配置每个单元格
  • 每次需要显示新的单元格时,都会实时创建新的单元格对象,不会尝试重用已存在的单元格

示例程序

- (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];}return cell;
}

两者的区别

  • 注册方法的代码更简洁,不需要手动检查 cell 是否为 nil,非注册方法需要更多的判断和创建新 cell 的代码。
  • 注册方法在获取可复用 cell 时更高效,因为系统可以直接从复用池中获取,非注册方法需要手动检查 cell 是否为 nil,并在需要时创建新的 cell,会稍微慢一些。

自定义cell

自定义 cell 可以让你更好地控制 cell 的外观和行为,提高代码的可读性和可维护性。同时,合理的复用机制也可以显著提高滚动性能。

自定义cell的具体步骤

  • 创建自定义cell类
  • 添加UI元素
  • 实现初始化方法
  • 设置cell的布局
  • 在TableView中使用自定义cell

示例程序
**先自己创建一个MyCell类,继承于UITableViewCell类,在该类中定义自己将使用的控件,并规定他们的位置等信息

MyCell.h

#import <UIKit/UIKit.h>NS_ASSUME_NONNULL_BEGIN@interface MyCell : UITableViewCell
@property UIButton* btn;
@property UILabel* label;
@property (nonatomic, strong) UISwitch* swt;
@end

MyCell.m

#import "MyCell.h"@implementation MyCell-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];if([self.reuseIdentifier isEqualToString:@"mycell"]) {_label = [[UILabel alloc] init];[self.contentView addSubview:_label];_swt = [[UISwitch alloc] init];_btn = [[UIButton alloc] init];[self.contentView addSubview:_btn];}return self;
}-(void)layoutSubviews{_btn.frame = CGRectMake(0, 0, 50, 50);_label.frame = CGRectMake(60, 0, 100, 50);
}@end

ViewContreller.m:

#import "ViewController.h"
#import "MyCell.h"
@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.self.view.backgroundColor = [UIColor whiteColor];self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];[self.view addSubview: self.tableView];self.tableView.dataSource = self;self.tableView.delegate = self;[self.tableView registerClass:[MyCell class] forCellReuseIdentifier:@"mycell"];}- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{return 2;
}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{return 4;
}- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{return 120;
}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{MyCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"mycell" forIndexPath:indexPath];if(indexPath.section == 1) {cell.label.text = @"Lee";[cell.btn setImage:[UIImage imageNamed:@"12.png"]  forState:UIControlStateNormal];} else {cell.label.text = @"Xxx";[cell.btn setImage:[UIImage imageNamed:@"im1.jpg"] forState:UIControlStateNormal];}return cell;
}@end

运行结果
在这里插入图片描述

这篇关于【iOS】自定义cell及其复用机制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1069060

相关文章

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

MySQL中的锁机制详解之全局锁,表级锁,行级锁

《MySQL中的锁机制详解之全局锁,表级锁,行级锁》MySQL锁机制通过全局、表级、行级锁控制并发,保障数据一致性与隔离性,全局锁适用于全库备份,表级锁适合读多写少场景,行级锁(InnoDB)实现高并... 目录一、锁机制基础:从并发问题到锁分类1.1 并发访问的三大问题1.2 锁的核心作用1.3 锁粒度分

Java实现自定义table宽高的示例代码

《Java实现自定义table宽高的示例代码》在桌面应用、管理系统乃至报表工具中,表格(JTable)作为最常用的数据展示组件,不仅承载对数据的增删改查,还需要配合布局与视觉需求,而JavaSwing... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

一文详解Java Stream的sorted自定义排序

《一文详解JavaStream的sorted自定义排序》Javastream中的sorted方法是用于对流中的元素进行排序的方法,它可以接受一个comparator参数,用于指定排序规则,sorte... 目录一、sorted 操作的基础原理二、自定义排序的实现方式1. Comparator 接口的 Lam

Redis的持久化之RDB和AOF机制详解

《Redis的持久化之RDB和AOF机制详解》:本文主要介绍Redis的持久化之RDB和AOF机制,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录概述RDB(Redis Database)核心原理触发方式手动触发自动触发AOF(Append-Only File)核

PostgreSQL中MVCC 机制的实现

《PostgreSQL中MVCC机制的实现》本文主要介绍了PostgreSQL中MVCC机制的实现,通过多版本数据存储、快照隔离和事务ID管理实现高并发读写,具有一定的参考价值,感兴趣的可以了解一下... 目录一 MVCC 基本原理python1.1 MVCC 核心概念1.2 与传统锁机制对比二 Postg

Maven 配置中的 <mirror>绕过 HTTP 阻断机制的方法

《Maven配置中的<mirror>绕过HTTP阻断机制的方法》:本文主要介绍Maven配置中的<mirror>绕过HTTP阻断机制的方法,本文给大家分享问题原因及解决方案,感兴趣的朋友一... 目录一、问题场景:升级 Maven 后构建失败二、解决方案:通过 <mirror> 配置覆盖默认行为1. 配置示

Redis过期删除机制与内存淘汰策略的解析指南

《Redis过期删除机制与内存淘汰策略的解析指南》在使用Redis构建缓存系统时,很多开发者只设置了EXPIRE但却忽略了背后Redis的过期删除机制与内存淘汰策略,下面小编就来和大家详细介绍一下... 目录1、简述2、Redis http://www.chinasem.cn的过期删除策略(Key Expir

如何自定义一个log适配器starter

《如何自定义一个log适配器starter》:本文主要介绍如何自定义一个log适配器starter的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录需求Starter 项目目录结构pom.XML 配置LogInitializer实现MDCInterceptor

Go语言中Recover机制的使用

《Go语言中Recover机制的使用》Go语言的recover机制通过defer函数捕获panic,实现异常恢复与程序稳定性,具有一定的参考价值,感兴趣的可以了解一下... 目录引言Recover 的基本概念基本代码示例简单的 Recover 示例嵌套函数中的 Recover项目场景中的应用Web 服务器中