iOS UI視圖面試相關

iOS UI視圖面試相關

UITableVIew相關

  • 重用機制
cell = [tableView dequeueReusableCellWillIdentifier:identifer];
image-20250706155208317

其中A2、A3、A4、A5是完全顯示在屏幕,A2、A6顯示部分,A1和A7不在顯示范圍內,假如現在是從下滑時的結果,在A1消失時會被放入到重用池,在A7顯示時從重用池里取一個cell來使用,如果cellA1-A7都是一個identifer,那么A7會拿到A1的cell來進行重用

復用池的實現:

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
// 實現重用機制的類
@interface ViewReusePool : NSObject// 從重用池當中取出一個可重用的view
- (UIView *)dequeueReusableView;// 向重用池當中添加一個視圖
- (void)addUsingView:(UIView *)view;// 重置方法,將當前使用中的視圖移動到可重用隊列當中
- (void)reset;@end
#import "ViewReusePool.h"@interface ViewReusePool ()
// 等待使用的隊列
@property (nonatomic, strong) NSMutableSet *waitUsedQueue;
// 使用中的隊列
@property (nonatomic, strong) NSMutableSet *usingQueue;
@end@implementation ViewReusePool- (id)init{self = [super init];if (self) {_waitUsedQueue = [NSMutableSet set];_usingQueue = [NSMutableSet set];}return self;
}- (UIView *)dequeueReusableView{UIView *view = [_waitUsedQueue anyObject];if (view == nil) {return nil;}else{// 進行隊列移動[_waitUsedQueue removeObject:view];[_usingQueue addObject:view];return view;}
}- (void)addUsingView:(UIView *)view
{if (view == nil) {return;}// 添加視圖到使用中的隊列[_usingQueue addObject:view];
}- (void)reset{UIView *view = nil;while ((view = [_usingQueue anyObject])) {// 從使用中隊列移除[_usingQueue removeObject:view];// 加入等待使用的隊列[_waitUsedQueue addObject:view];}
}@end
  • 數據源同步
image-20250706163446910

刪除一般是在主線程操作,刪除時往往會觸發后向刷新LoadMore,這就涉及到多線程對共享數據的訪問,需要考慮數據源同步問題,解決方案:

  • 并發訪問、數據拷貝
image-20250706163902920

在子線程請求數據時,主線程做了刪除操作,導致數據不同步

主線程記錄刪除操作,在子線程中返回數據前同步刪除操作

image-20250706164110828
  • 串行訪問

子線程進行網絡請求、數據解析,網絡請求回來時在串行隊列去進行新增數據預排版(子線程當中),在這期間主線程刪除了某個數據,在串行隊列當中前一個block完成之后去執行同步主線程發送過來的任務同步數據刪除,然后再去回到主線程更新UI。

image-20250706164957876

事件傳遞 & 視圖響應

UIVIew和CALayer的區別

  • UIView為其提供內容,以及負責處理觸摸等事件,參與響應鏈
  • CALayer負責顯示內容contents

UIView實際上是對CALayer的輕量級封裝。每個UIView都有一個關聯的CALayer作為其backing store,負責實際的渲染工作,而UIView則處理用戶交互和事件響應。CALayer通過contents屬性提供要顯示的位圖信息,UIView繼承自UIResponder,而CALayer繼承自NSObject,UIView主要負責處理用戶交互,如觸摸、點擊和拖動等事件。而CALayer則專注于渲染和動畫處理

事件傳遞與視圖響應鏈

假如點擊了c2的空白區域,系統最終怎么樣找到響應視圖為c2的?

image-20250706170637631
事件傳遞:尋找最佳響應者(Hit-Testing)
image-20250706171102674

事件傳遞是從父控件到子控件的正向傳遞過程點擊屏幕 → UIApplication → UIWindow → 父視圖 → 子視圖),目標是找到最合適的視圖(Hit-Test View)處理觸摸事件。

  1. 核心方法

    • hitTest:withEvent::遞歸調用子視圖的該方法,返回最終處理事件的視圖。
    • pointInside:withEvent::判斷觸摸點是否在視圖范圍內,是hitTest的底層依賴方法
  2. 傳遞規則

    image-20250706171937365
    • UIWindow開始,遍歷子視圖(從后往前,即最上層的子視圖優先)。
    • 若視圖滿足以下條件,則繼續向其子視圖傳遞:
      • userInteractionEnabled = YES
      • hidden = NO
      • alpha > 0.01
      • 觸摸點在視圖范圍內(通過pointInside驗證)。
    • 若當前視圖無子視圖或子視圖不滿足條件,則自身成為最佳響應者。
  3. 特性

    • 即使父視圖是最佳響應者,仍會遞歸調用所有子視圖的hitTest方法(確保無更合適的子視圖)5。
    • 可重寫hitTest:withEvent:實現特殊事件攔截(如擴大按鈕點擊區域)。
響應鏈:事件處理流程

當最佳響應者無法處理事件時,事件沿響應鏈反向傳遞(從子控件到父控件),直至被處理或丟棄。

  1. 響應鏈構成
    響應鏈由UIResponder對象(UIViewUIViewController等)通過nextResponder連接:

    最佳響應視圖 → 父視圖 → ... → 控制器 → UIWindow → UIApplication → AppDelegate
    
    • 視圖的nextResponder:若視圖是控制器的根視圖,則指向控制器;否則指向父視圖。
    • 控制器的nextResponder:指向其視圖的父視圖或UIWindow
  2. 事件響應邏輯

    • 最佳響應者優先處理事件(如實現touchesBegan:withEvent:)。
    • 若未處理,調用[super touchesBegan...]將事件傳遞給nextResponder
    • 若響應鏈中所有對象均未處理,事件被靜默丟棄(不會崩潰)。

UI卡頓掉幀

image-20250713111644302

通常情況下,屏幕刷新率為60Hz,意味著每秒需要渲染60幀畫面,即每幀的渲染時間不應超過16.7毫秒。如果某一幀的渲染時間超過了16.7毫秒,就會導致卡頓或掉幀現象,影響用戶體驗

繪制原理

image-20250713112834763

為什么調用[UIView setNeedsDisplay]并沒有立即進行視圖的繪制工作?

在當前Runloop將要結束才會介入UI視圖的繪制流程當中

異步繪制

  • 異步繪制:通過實現 CALayer 的代理方法 displayLayer,在子線程中生成位圖,減少主線程的負擔。
image-20250713114045209

離屏渲染

在屏渲染:也為當前屏幕渲染,GPU的渲染操作是在當前用于顯示的屏幕緩沖區中進行

離屏渲染:GPU在當前屏幕緩沖區以外新開辟一個緩沖區進行渲染操作

避免離屏渲染:盡量避免使用 layer 的圓角、邊框、陰影等屬性,這些屬性會觸發離屏渲染,增加 GPU 的負擔,可能導致GPU和CPU的總耗時超過16.7ms,可能會掉幀,可以在后臺線程預先繪制好對應內容,減少 GPU 的工作量。

常見的觸發離屏渲染的屬性

  1. 圓角 (cornerRadius)
    • 當設置 layer.cornerRadius 屬性并且 masksToBoundsYES 時,會觸發離屏渲染。這是因為 masksToBounds 會應用到所有的圖層上,需要在離屏緩沖區中進行圓角裁剪處理。
    • 如果 layer 只有一個圖層且沒有 content,設置 cornerRadiusmasksToBounds 不會觸發離屏渲染。
  2. 陰影 (shadow\*)
    • 當設置 layer.shadow* 屬性時,如果陰影路徑(shadowPath)沒有設置,系統需要離屏渲染來計算陰影。陰影需要在所有內容繪制完成后根據外輪廓進行繪制,因此需要在離屏緩沖區中進行處理。
  3. 圖層蒙版 (mask)
    • 使用 layer.mask 或者 layer.masksToBounds 時會觸發離屏渲染。這是因為蒙版需要在離屏緩沖區中進行剪裁處理。
  4. 組透明度 (group opacity)
    • 設置 layer.allowsGroupOpacity 或者 layer.opacity 時,如果 opacity 小于1,會觸發離屏渲染。這是因為透明度需要在離屏緩沖區中進行混合處理。
  5. 光柵化 (shouldRasterize)
    • 開啟 layer.shouldRasterize 會觸發離屏渲染。光柵化會將 layer 的渲染結果保存在離屏緩沖區中,以便在后續幀中復用,減少重復渲染的開銷

滑動優化方案

基于tableview、scrollview的滑動優化方案

  • CPU方面

可以在子線程進行一些對象創建、調整、銷毀、包括進行預排版(布局計算、文本計算)、預渲染(文本等異步繪制、圖片編解碼等)

  • GPU方面

避免離屏渲染,盡量避免使用 layer 的圓角、邊框、陰影等屬性,這些屬性會觸發離屏渲染,增加 GPU 的負擔

異步繪制:通過實現 CALayer 的代理方法 displayLayer,在子線程中生成位圖,減少主線程的負擔。例如,微博的頭像在下載后會在后臺線程預先渲染為圓形并保存到緩存中,這樣可以減少主線程的渲染壓力。

復用機制:不要一次性創建所有子視圖,而是在需要時創建,并復用它們。這樣可以減少內存分配的開銷,節省內存空間。UITableView 和 UICollectionView 的復用機制就是一個很好的例子。

懶加載:把創建對象的時機延后到不得不需要它們的時候,減少初始加載時間。

按需加載:在滑動過程中,按需加載對應的內容。例如,當目標行與當前行相差超過指定行數時,只在目標滾動范圍的前后指定幾行加載,減少不必要的加載操作。

自動加載更新數據:在滾動到特定位置時,自動加載更多數據,減少用戶等待時間。

面試問題總結:

  1. 系統的UI事件傳遞機制是怎樣的?
  2. 使UITableView滾動更流暢的方案或思路都有哪些?
  3. 什么是離屏渲染?
  4. UIView和CALayer之間的關系是怎樣的?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/914616.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/914616.shtml
英文地址,請注明出處:http://en.pswp.cn/news/914616.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

網絡編程-tcp連接:服務器與客戶端

使用服務器和客戶端的代碼&#xff0c;實現服務器和客戶端的互相聊天功能 實現兩臺電腦之間互相聊天 方案一&#xff1a;服務器代碼&#xff08;server.c&#xff09;#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h>…

跨平臺移動開發技術深度分析:uni-app、React Native與Flutter的遷移成本、性能、場景與前景

1. 引言 跨平臺移動開發技術已成為提升開發效率、降低成本的戰略性選擇。uni-app、React Native&#xff08;RN&#xff09;和Flutter作為主流方案&#xff0c;在遷移成本、應用性能、適用場景及未來發展上呈現顯著差異。本報告基于最新行業數據與技術演進&#xff08;2025年&…

詳解低速容錯CAN(附與高速CAN對比表)

文章目錄前言一、低速容錯CAN-低速二、低速容錯CAN-容錯2.1 信號電平2.2 終端電阻2.3 容錯機制前言 在ISO 11898-3 Low-speed, fault-tolerant, medium-dependent interface部分描述了低速CAN的容錯行為及其物理層內容。既然稱為低速容錯CAN&#xff0c;主要需要搞清楚的兩個核…

維基框架發布 1.0.11 至中央倉,深化國產化 DevOps 生態整合

一、核心事件&#xff1a;維基框架 1.0.11 正式入駐中央倉庫? ?維基框架&#xff08;Wiki-Framework&#xff09;?? 作為國產全場景 Java 企業級開發框架&#xff0c;于 7 月 9 日正式發布 ?v1.0.11 版本? 至中央軟件倉庫&#xff08;Maven Central&#xff09;&#xf…

vscode 打開c++文件注釋亂碼

之前一直都主要用vscode編輯lua和python腳本語言&#xff0c;沒怎么編輯過c文件&#xff0c;今天想打開一個文件看一個東西&#xff0c;但是注釋全部亂碼了&#xff0c;我也知道是文件編碼的問題&#xff0c;但沒找到修改編碼格式的地方&#xff0c;好了廢話不多說&#xff0c;…

波動回升正當時!期權合成多頭:震蕩市攻守兼備利器

上周&#xff0c;A股喜提關鍵突破&#xff01;上證指數自21年初以來首次穩穩站上3500點大關&#xff0c;市場整體震蕩上行。尐程序&#xff1a;期權匯不過&#xff0c;熱鬧之下也藏有隱憂&#xff1a;雖然日均成交維持在1.4萬億加&#xff0c;但周五放量沖高&#xff08;成交達…

Python 基礎(十四): 錯誤和異常

目錄 1 錯誤2 異常 2.1 內置異常2.2 異常處理2.3 拋出異常2.4 自定義異常 程序中的錯誤我們通常稱為 bug &#xff0c;工作中我們不僅需要改自己程序中的 bug &#xff0c;還需要改別人程序中的 bug &#xff0c;新項目有 bug 要改&#xff0c;老項目也有 bug 要改&#xff…

OpenCV-Python Tutorial : A Candy from Official Main Page(三)

3.11傅立葉變換3.11.1Fourier Transform in OpenCV-cv.dft、cv.magnitude、cv.idft這兩個函數是圖像頻域處理&#xff08;如去噪、邊緣增強、紋理分析&#xff09;的基礎工具。1.cv.dft() —— 離散傅里葉變換功能&#xff1a; 將圖像從空間域&#xff08;像素強度&#xff09;…

移動端字體適配

一、移動端圖片適配1、使用 <img> 的 srcset<img src"logo.png"srcset"logo2x.png 2x,logo3x.png 3x"alt"Logo">優點&#xff1a;原生支持&#xff0c;瀏覽器自動選擇最合適的圖片。2、使用媒體查詢切換背景圖.logo {background-ima…

git起步

git官網&#xff1a;https://git-scm.com git使用手冊&#xff1a;https://git-scm.com/book/zh/v2 一、Git 是什么&#xff1f; 1、版本控制 版本控制是一種記錄一個或若干文件內容變化&#xff0c;以便將來查閱特定版本修訂情況的系統。我們經常是用的是保存軟件源代碼的…

SSL與HTTP概述

一、概念1.SSL概念SSL&#xff08;Secure Sockets Layer&#xff09;是一種網絡安全協議&#xff0c;用于在互聯網通信中建立加密鏈接&#xff0c;保護在網絡中傳輸的敏感數據免遭竊取或篡改。2.TLS概念雖然現在更先進的 TLS&#xff08;Transport Layer Security&#xff09; …

前端報錯:“Uncaught SyntaxError: missing ) after argument list

問題描述&#xff1a;前端報錯&#xff1a;“Uncaught SyntaxError: missing ) after argument list在 JavaScript 中遇到“SyntaxError: missing ) after argument list”這個錯誤通常意味著在函數調用或者聲明中&#xff0c;參數列表的括號沒有正確閉合。錯誤代碼&#xff1a…

廣州郵科光纖交換機的應用:網絡世界中的幕后核心

你知道嗎&#xff1f;在我們每天暢游互聯網&#xff0c;發送郵件、看視頻、打游戲時&#xff0c;背后支撐這一切流暢體驗的關鍵設備之一就是光纖交換機。它像一個幕后英雄&#xff0c;默默地確保信息傳輸高效、穩定。那么&#xff0c;究竟郵科光纖交換機有哪些不可或缺的應用領…

C++內存布局、構造函數規則和優化策略解析

一、類對象內存布局深度解析 1.1 核心內存占用規則 ?非靜態成員變量?&#xff1a;每個對象獨立存儲&#xff0c;按聲明順序排列&#xff08;含內存對齊填充&#xff09; 示例&#xff1a;class A{int x; char y;}; → 實際占用8字節&#xff08;413填充&#xff09;4?靜態…

Fastapi框架總覽與核心架構

Fastapi框架總覽與核心架構 FastAPI 是一個基于 Python 的現代 Web 框架&#xff0c;專注于 高性能、高并發 和 開發效率&#xff0c;特別適合構建 異步 API 服務、微服務接口&#xff0c;同時在大模型接口封裝中也廣泛應用。它基于 Starlette&#xff08;異步 Web 框架&#x…

高并發四種IO模型的底層原理

高并發四種IO模型的底層原理 1 IO讀寫的基本原理 為了避免用戶進程直接操作內核&#xff0c;保證內核安全&#xff0c;操作系統將內存&#xff08;虛擬內存&#xff09;劃分為兩部分&#xff1a;一部分是內核空間(Kernel-Space)&#xff0c;另一部分是用戶空間(User-Space)。在…

騰訊云短信實戰:Spring Boot接入YML配置與簽名/模板/發送/統計/狀態/號碼包工具類詳解

下面是一個Spring Boot集成騰訊云短信服務的詳細示例&#xff0c;包含配置和6個工具類&#xff08;簽名、模板、發送、統計、狀態&#xff09;&#xff0c;采用YML配置&#xff1a; 1. 添加Maven依賴 <dependency><groupId>com.tencentcloudapi</groupId>&…

【Java篇】IntelliJ IDEA 安裝與基礎配置指南

序 本篇文章將介紹IDEA 2023 版本。 提高開發人員的生產力。無論您是剛開始接觸編程的新手&#xff0c;還是經驗豐富的開發專家。 一&#xff1a;官網下載安裝包&#xff1a; IDEA下載鏈接 這個版本可以根據自己的需要選擇。 二、安裝方法 雙擊進這個.exe文件 這里要選擇合…

2-Nodejs運行JS代碼

2-Nodejs運行JS代碼 創建一個 js 文件編寫 JS 代碼 要注意的是&#xff0c;在nodejs環境中不能操作瀏覽器 DOM 對象相關的api&#xff0c;在Nodejs 中運行 JS 代碼 按住 shift 鍵&#xff0c;在 js 文件所在文件夾空白處右鍵&#xff0c;選擇 Powershell 窗口執行如下命令&…

vue中使用西瓜播放器xgplayer (封裝)+xgplayer-hls 播放.m3u8格式視頻

1.西瓜播放器官網 http://h5player.bytedance.com/guide/2.安裝 # 最新穩定版 $ npm install xgplayer對于已有項目也可以通過 CDN 引入&#xff0c;代碼如下&#xff1a; <script src"//unpkg.byted-static.com/xgplayer/2.31.2/browser/index.js" type"tex…