iOS App的啟動與優化

App的啟動流程

App啟動分為冷啟動和熱啟動

  • 冷啟動:從0開始啟動App
  • 熱啟動:App已經在內存中,但是后臺還掛著,再次點擊圖標啟動App。

一般對App啟動的優化都是針對冷啟動。

App冷啟動可分為三個階段:

  1. dyld:加載鏡像、動態庫
  2. RunTime方法
  3. main函數初始化

動態庫vs靜態庫

靜態庫:一堆.o文件的集合(通常是.a后綴),還沒有被鏈接過,缺點是產物體積比較大,優點是鏈接到App之后體積比較小。

動態庫:一個已經鏈接完全的鏡像,優點是產物體積比較小,缺點是鏈接到App之后體積比較大。

兩者最大的區別就是靜態庫沒有被鏈接過,而動態庫被鏈接過。

一.dyld

dyld是app的動態鏈接器。主要可以用來裝載Mach-O文件(可執行文件、動態庫等)

啟動APP時,dyld所做的事情有:

加載過程從exec()函數開始,這是一個系統調用。操作系統首先為進程分配一段內存空間。然后執行以下操作:

  • 1.把App的可執行文件加載到內存
  • 2.把dyld加載到內存
  • 3.dyld進行動態鏈接

具體內容:

  • 1、加載動態庫
    • Dyld從主執行文件的header獲取到需要加載的所依賴動態庫列表,然后它需要找到每個 dylib,而應用所依賴的 dylib 文件可能會再依賴其他 dylib,所以所需要加載的是動態庫列表一個遞歸依賴的集合
  • 2、Rebase和Binding
    • 1、Rebase(偏移修正)

      ? ? ? ?任何一個app生成的二進制文件,在二進制文件內部所有的方法、函數調用,都有一個地址,這個地址是在當前二進制文件中的偏移地址。一旦在運行時刻(即運行到內存中),每次系統都會隨機分配一個ASLR(Address Space Layout Randomization,地址空間布局隨機化)地址值(是一個安全機制,會分配一個隨機的數值,插入在二進制文件的開頭),例如,二進制文件中有一個 test方法,偏移值是0x0001,而隨機分配的ASLR是0x1f00,如果想訪問test方法,其內存地址(即真實地址)變為 ASLR+偏移值 = 運行時確定的內存地址(即0x1f00+0x0001 = 0x1f01)

    • 2、Binding(綁定)

      ? ? ? ?例如NSLog方法,在編譯時期生成的mach-o文件中,會創建一個符號!NSLog(目前指向一個隨機的地址),然后在運行時(從磁盤加載到內存中,是一個鏡像文件),會將真正的地址給符號(即在內存中將地址與符號進行綁定,是dyld做的,也稱為動態庫符號綁定),一句話概括:綁定就是給符號賦值的過程

二.RunTime階段

dyld階段結束之后就進入RunTime階段,這個階段主要進行如下內容:

1、Objc setup

  • 1、注冊Objc類 (class registration)
  • 2、把category的定義插入方法列表 (category registration)
  • 3、保證每一個selector唯一 (selector uniquing)

2、Initializers

  • 1、Objc的+load()函數
  • 2、C++的構造函數屬性函數
  • 3、非基本類型的C++靜態全局變量的創建(通常是類或結構體)

三.main()函數初始化

App的啟動由dyld主導,把可執行文件加載到內存,并且加載所有依賴的動態庫,并由RunTime負責加載成objc定義的結構,所有初始化工作結束后,dyld就會調用mainn函數 接下來就是UIApplicationMain函數,AppDelegate的application:didFinishLaunchingWithOptions:方法

這個里面往往是最占用啟動時間的地方,同時也是我們最為可控的地方。

? 進入 main() 函數,啟動應用。

? 執行 UIApplicationMain() 函數,創建 UIApplication 對象并設置 AppDelegate。

? 加載應用的主 UI,包括 storyboard 或 xib 文件,以及 AppDelegate 的各種生命周期方法,如 application:didFinishLaunchingWithOptions:。

四.首屏渲染階段

初始化rootViewController,加載和渲染界面

渲染完成后,用戶將看到應用的首屏。

?

App冷啟動流程總結:

1. dyld 加載階段:

? 動態鏈接器 dyld 負責加載應用的可執行文件及其依賴的動態庫。此時,系統將會做如下工作:

? 查找應用的可執行文件和動態庫

? 將它們加載到內存中

? 進行符號解析和綁定

? 執行初始化函數(如 +load 方法和靜態構造函數)

2. runtime 初始化階段:

? ObjC 運行時對類和分類進行注冊。

? 執行各類 +load 方法,這個階段還會進行一些 Swift 類的初始化。

3. main() 函數執行階段:

? 進入 main() 函數,啟動應用。

? 執行 UIApplicationMain() 函數,創建 UIApplication 對象并設置 AppDelegate。

? 加載應用的主 UI,包括 storyboard 或 xib 文件,以及 AppDelegate 的各種生命周期方法,如 application:didFinishLaunchingWithOptions:。

4. 首屏渲染階段:

? 初始化 rootViewController,加載和渲染界面。

? 渲染完成后,用戶將看到應用的首屏。

+load與+initialize

1、+load

(1)+load方法是一定會在runtime中被調用的。只要類被添加到runtime中了,就會調用+load方法,因此+load方法總是在main函數之前調用

(2)+load方法不會覆蓋。也就是說,如果子類實現了+load方法,那么會先調用父類的+load方法(無需手動調用super),然后又去執行子類的+load方法。

(3)+load方法只會調用一次。

(4)+load方法執行順序是:類 -> 子類 ->分類。而不同分類之間的執行順序不一定,依據在Compile Sources中出現的順序(先編譯,則先調用,列表中在下方的為“先”)。

(5)+load方法是函數指針調用,即遍歷類中的方法列表,直接根據函數地址調用。如果子類沒有實現+load方法,子類也不會自動調用父類的+load方法。

2、+initialize

(1)+initialize方法是在類或它的子類收到第一條消息之前被調用的,這里所指的消息包括實例方法和類方法的調用。因此+initialize方法總是在main函數之后調用

(2)+initialize方法只會調用一次。

(3)+initialize方法實際上是一種惰性調用,如果一個類一直沒被用到,那它的+initialize方法也不會被調用,這一點有利于節約資源。

(4)+initialize方法會覆蓋。如果子類實現了+initialize方法,就不會執行父類的了,直接執行子類本身的。如果分類實現了+initialize方法,也不會再執行主類的。

(5)+initialize方法的執行覆蓋順序是:分類 -> 子類 ->類。且只會有一個+initialize方法被執行

(6)+initialize方法是發送消息(objc_msgSend()),如果子類沒有實現+initialize方法,也會自動調用其父類的+initialize方法。

3、兩者的異同

(1)相同點

  1. load和initialize會被自動調用,不能手動調用它們。
  2. 子類實現了load和initialize的話,會隱式調用父類的load和initialize方法。
  3. load和initialize方法內部使用了鎖,因此它們是線程安全的。

(2)不同點

  1. 調用順序不同,以main函數為分界,+load方法在main函數之前執行,+initialize在main函數之后執行。(存疑)
  2. 子類中沒有實現+load方法的話,子類不會調用父類的+load方法;而子類如果沒有實現+initialize方法的話,也會自動調用父類的+initialize方法。
  3. +load方法是在類被裝在進來的時候就會調用,+initialize在第一次給某個類發送消息時調用(比如實例化一個對象),并且只會調用一次,是懶加載模式,如果這個類一直沒有使用,就不回調用到+initialize方法。

4、使用場景

(1)+load一般是用來交換方法,由于它是線程安全的,而且一定會調用且只會調用一次,通常在使用UrlRouter的時候注冊類的時候也在+load方法中注冊。
(2)+initialize方法主要用來對一些不方便在編譯期初始化的對象進行賦值,或者說對一些靜態常量進行初始化操作。

冷啟動時間優化

1.減少動態庫(dyld階段)

一般不多于6個,多余需要進行合并,動態庫越多,dyld階段加載時間越長。

2.減少類和方法的數量

3.延遲初始化(rebase/Binging階段)

盡量延遲一些不必要的初始化工作,不要在啟動時立即初始化所有對象。可以使用懶加載將一些初始化放到用戶需要時再進行,以減輕啟動階段的負擔。

4. 避免 +load 方法的使用(Initializers階段)

+load 方法會在 dyld 加載階段執行,建議用 +initialize 或者在合適的地方延遲執行初始化邏輯,避免阻塞啟動流程。

5.優化 AppDelegate(main()階段)

application:didFinishLaunchingWithOptions: 方法應保持精簡,避免在這里進行耗時的操作。將一些耗時任務放到后臺隊列中異步執行。

6.減少主線程阻塞

啟動階段盡量避免主線程的耗時操作,如文件 I/O、網絡請求等。將這些操作放到子線程處理,以免阻塞界面渲染。

7.預編譯和瘦身

移除未使用的代碼、圖片等資源,精簡應用的體積,從而減少加載時間。

盡量減少 storyboard 的使用,尤其是大而復雜的 storyboard,可以分解成多個小的 storyboard 或者使用純代碼實現界面。

8.啟動時的網絡請求

盡量避免在啟動時進行同步的網絡請求,如果必須請求,可以在啟動完成后或在后臺進行異步請求,以減少對啟動時間的影響。
?

參考:

iOS--App啟動過程及優化_ios啟動優化-CSDN博客

https://juejin.cn/post/6951591401528229895?searchId=202502182003101C89E818EB9B45117D0A

JHBlog/iOS知識點/iOS大雜燴/APP啟動優化/App啟動時間優化.md at master · SunshineBrother/JHBlog · GitHub

?

?

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

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

相關文章

oppo,湯臣倍健,康冠科技25屆春招內推

oppo,湯臣倍健,康冠科技25屆春招內推 ①康冠科技25屆春招 【職位】算法、軟件、硬件、技術,結構設計,供應鏈,產品,職能,商務 【一鍵內推】https://sourl.cn/2Mm9Lk 【內推碼】EVBM88 ②湯臣倍健…

centos 9 時間同步服務

在 CentOS 9 中,默認的時間同步服務是 chrony,而不是傳統的 ntpd。 因此,建議使用 chrony 來配置和管理時間同步。 以下是使用 chrony 配置 NTP 服務的步驟: 1. 安裝 chrony 首先,確保系統已安裝 chrony。 在 CentOS…

解鎖 Python 導入系統:從基礎到進階的深度指南

本文全面解讀 Python 導入系統,從導入機制的基礎概念,如模塊、包的導入方式,到查找、加載模塊的詳細過程,再到導入系統的高級特性和應用場景,通過豐富示例、直觀圖表和對比分析,助你深入理解并熟練運用導入…

DDoS技術解析

這里是Themberfue 今天我們不聊別的,我們聊聊著名的網絡攻擊手段之一的 DDoS,看看其背后的技術細節。 DoS 了解 DDoS 前,先來講講 DoS 是什么,此 DoS 而不是 DOS 操作系統啊。1996年9月6日,世界第三古老的網絡服務提供…

docker安裝kafka,并通過springboot快速集成kafka

目錄 一、docker安裝和配置Kafka 1.拉取 Zookeeper 的 Docker 鏡像 2.運行 Zookeeper 容器 3.拉取 Kafka 的 Docker 鏡像 4.運行 Kafka 容器 5.下載 Kafdrop 6.運行 Kafdrop 7.如果docker pull wurstmeister/zookeeper或docker pull wurstmeister/kafka下載很慢&#x…

C++ 與 Java 的對比分析:除法運算中的錯誤處理

博客主頁: [小????????] 本文專欄: Java 文章目錄 💯前言💯C中的除法錯誤處理💯Java中的除法錯誤處理💯C與Java錯誤處理的對比💯錯誤處理的優化和實踐💯小結 💯前言 在…

LLM之循環神經網絡(RNN)

在人工智能的領域中,神經網絡是推動技術發展的核心力量。今天,讓我們深入探討循環神經網絡(RNN) 一、神經網絡基礎 (1)什么是神經網絡 神經網絡,又稱人工神經網絡,其設計靈感源于人…

SQL sever數據導入導出實驗

1.創建數據庫TCP-H (1)右鍵“數據庫”,點擊“新建數據庫”即可 (2)用sql語言創建,此處以創建數據庫DB_test為例,代碼如下: use master;go--檢查在當前服務器系統中的所有數據里面…

讓編程變成一種享受-明基RD320U顯示器

引言 作為一名有著多年JAVA開發經驗的從業者,在工作過程中,顯示器的重要性不言而喻。它不僅是我們與代碼交互的窗口,更是影響工作效率和體驗的關鍵因素。在多年的編程生涯中,我遇到過各種各樣的問題。比如,在進行代碼…

計算機網絡(涵蓋OSI,TCP/IP,交換機,路由器,局域網)

一、網絡通信基礎 (一)網絡通信的概念 網絡通信是指終端設備之間通過計算機網絡進行的信息傳遞與交流。它類似于現實生活中的物品傳遞過程:數據(物品)被封裝成報文(包裹),通過網絡…

圖像處理篇---基本OpenMV圖像處理

文章目錄 前言1. 灰度化(Grayscale)2. 二值化(Thresholding)3. 掩膜(Mask)4. 腐蝕(Erosion)5. 膨脹(Dilation)6. 縮放(Scaling)7. 旋轉…

SpringMVC重定向接口,參數暴露在url中解決方案!RedirectAttributes

OK,首先描述下業務場景,終端數量限制登錄 1.首先訪問項目login的get接口 2.輸入賬號密碼點擊登錄后,會請求login的POST接口 3.后臺對終端數量邏輯處理不允許登錄跳回到登錄頁面 4.因代碼原因需在后臺進行多次重定向接口,最后跳…

Spring Boot01(注解、)---java八股

Spring Boot中常用注解及其底層實現 1、SpringBootApplication注解: SpringBootApplication注解:這個注解標識了一個SpringBoot工程,它實際上是另外三個注解的組合,這三個注解是: aSpringBootConfiguration&#xff1a…

?2.快速了解HTML5的標簽類型

??HTML5 的標簽類型豐富多樣&#xff0c;每種類型都有其獨特的功能和用途&#xff0c;以下是一些常見的 HTML5 標簽類型介紹&#xff1a; &#x1f98b;結構標簽 &#x1faad;<html>&#xff1a;它是 HTML 文檔的根標簽&#xff0c;所有其他標簽都包含在這個標簽內&am…

eNSP防火墻綜合實驗

一、實驗拓撲 二、ip和安全區域配置 1、防火墻ip和安全區域配置 新建兩個安全區域 ip配置 Client1 Client2 電信DNS 百度web-1 聯通DNS 百度web-2 R2 R1 三、DNS透明代理相關配置 1、導入運營商地址庫 2、新建鏈路接口 3、配置真實DNS服務器 4、創建虛擬DNS服務器 5、配置D…

Linux 配置交換空間(Swap)解決內存不足

&#x1f680; 作者主頁&#xff1a; 有來技術 &#x1f525; 開源項目&#xff1a; youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template &#x1f33a; 倉庫主頁&#xff1a; GitCode︱ Gitee ︱ Github &#x1f496; 歡迎點贊 &#x1f44d; 收藏 ?評論 …

個人shell腳本分享

在周一到周五做增量備份&#xff0c;在周六周日做完全備份 #!/bin/bash定義變量 SRC“/path/to/source” # 源目錄 BKUP“/backup” # 備份主目錄 FUL“KaTeX parse error: Expected EOF, got # at position 22: …ull" #? 完全備份目錄 INC"BKUP/inc” # 增量備份…

Django 5 實用指南(一)安裝與配置

1.1 Django5的背景與發展 Django 自從2005年由Adrian Holovaty和Simon Willison在 Lawrence Journal-World 新聞網站上首次發布以來&#xff0c;Django 一直是 Web 開發領域最受歡迎的框架之一。Django 框架經歷了多個版本的演進&#xff0c;每次版本更新都引入了新功能、改進了…

百度搜索融合 DeepSeek 滿血版,開啟智能搜索新篇

百度搜索融合 DeepSeek 滿血版&#xff0c;開啟智能搜索新篇 &#x1f680; &#x1f539; 一、百度搜索全量接入 DeepSeek &#x1f539; 百度搜索迎來重要升級&#xff0c;DeepSeek 滿血版全面上線&#xff01;&#x1f389; 用戶在百度 APP 搜索后&#xff0c;點擊「AI」即…

RabbitMQ服務異步通信

消息隊列在使用過程中&#xff0c;面臨著很多實際問題需要思考&#xff1a; 1. 消息可靠性 消息從發送&#xff0c;到消費者接收&#xff0c;會經理多個過程&#xff1a; 其中的每一步都可能導致消息丟失&#xff0c;常見的丟失原因包括&#xff1a; 發送時丟失&#xff1a; 生…