【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
繁體地址,請注明出處:http://hk.pswp.cn/diannao/86534.shtml
英文地址,請注明出處:http://en.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;通常來說有兩種解決方案。第一…