[iOS] ViewController 的生命周期

文章目錄

  • 前言
  • 一、UIViewController 生命周期有關函數
  • 二、UIViewController 中函數的執行順序
    • 運行結果
      • 1.present和dismiss
      • 2.push和pop
  • 三、總結

前言

UIViewController 是在 iOS 開發中一個非常重要的角色,他是 view 和 model 的橋梁,通過 UIViewController 的管理將數據展示在視圖上。與此同時作為 uikit 中最基本的一個類,一般復雜的項目都離不開 UIViewController 作為基類,所以了解 UIViewController 的生命周期是很重要的。

一、UIViewController 生命周期有關函數

下圖是 UIViewController 生命周期方法的調用函數

請添加圖片描述

二、UIViewController 中函數的執行順序

下面我會給出代碼這段代碼是將兩個視圖之間進行轉換,同時打印相關的函數名來觀察他的生命周期。在這里我給了兩種方式來展示出他的轉換,一個是 push 一個是 present。

#import "ViewControllerA.h"
#import "ViewControllerB.h"
@interface ViewControllerA ()
@property (nonatomic, strong) UIButton *btn1;
@property (nonatomic, strong) UIButton *btn2;
@end@implementation ViewControllerA- (void)viewDidLoad {[super viewDidLoad];self.view.backgroundColor = [UIColor blueColor];_btn1 = [UIButton buttonWithType:UIButtonTypeSystem];[_btn1 setTitle:@"next_view" forState:UIControlStateNormal];_btn1.frame = CGRectMake(self.view.frame.size.width / 2 - 50, self.view.frame.size.height / 2 - 50, 200, 100);[self.view addSubview:_btn1];[_btn1 addTarget:self action:@selector(Next_present) forControlEvents:UIControlEventTouchUpInside];_btn2 = [UIButton buttonWithType:UIButtonTypeSystem];[_btn2 setTitle:@"next_view" forState:UIControlStateNormal];_btn2.frame = CGRectMake(self.view.frame.size.width / 2 - 50, self.view.frame.size.height / 2 + 150, 200, 100);[self.view addSubview:_btn2];[_btn2 addTarget:self action:@selector(Next_push) forControlEvents:UIControlEventTouchUpInside];NSLog(@"%s", __func__);
}
- (void) Next_present {ViewControllerB *b = [[ViewControllerB alloc] init];NSLog(@"--------a->b---------");b.modalPresentationStyle = UIModalPresentationFullScreen;[self presentViewController:b animated:YES completion:nil];
}
- (void) Next_push {ViewControllerB *b = [[ViewControllerB alloc] init];NSLog(@"--------a->b---------");[self.navigationController pushViewController:b animated:YES];
}
- (void)loadView {[super loadView];NSLog(@"%s", __func__);
}
- (void)viewWillAppear:(BOOL)animated {NSLog(@"%s", __func__);
}
- (void)viewWillLayoutSubviews {NSLog(@"%s", __func__);
}
- (void)viewDidLayoutSubviews {NSLog(@"%s", __func__);
}
- (void)viewDidAppear:(BOOL)animated {NSLog(@"%s",__func__);
}
- (void)viewWillDisappear:(BOOL)animated {NSLog(@"%s", __func__);
}
- (void)viewDidDisappear:(BOOL)animated {NSLog(@"%s", __func__);
}
/*
#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {// Get the new view controller using [segue destinationViewController].// Pass the selected object to the new view controller.
}
*/@end
#import "ViewControllerB.h"
#import "ViewControllerA.h"
@interface ViewControllerB ()
@property (nonatomic, strong) UIButton *btn1;
@property (nonatomic, strong) UIButton *btn2;
@end@implementation ViewControllerB- (void)viewDidLoad {[super viewDidLoad];self.view.backgroundColor = [UIColor redColor];_btn1 = [UIButton buttonWithType:UIButtonTypeSystem];[_btn1 setTitle:@"next_dismiss" forState:UIControlStateNormal];_btn1.frame = CGRectMake(self.view.frame.size.width / 2 - 50, self.view.frame.size.height / 2 - 50, 200, 100);[self.view addSubview:_btn1];[_btn1 addTarget:self action:@selector(Next_dismiss) forControlEvents:UIControlEventTouchUpInside];_btn2 = [UIButton buttonWithType:UIButtonTypeSystem];[_btn2 setTitle:@"next_pop" forState:UIControlStateNormal];_btn2.frame = CGRectMake(self.view.frame.size.width / 2 - 50, self.view.frame.size.height / 2 + 150, 200, 100);[self.view addSubview:_btn2];[_btn2 addTarget:self action:@selector(Next_pop) forControlEvents:UIControlEventTouchUpInside];NSLog(@"%s", __func__);
}
- (void) Next_dismiss {NSLog(@"--------b->a---------");[self dismissViewControllerAnimated:YES completion:nil];
}
- (void) Next_pop {NSLog(@"--------b->a---------");[self.navigationController popViewControllerAnimated:YES];
}
- (void)loadView {[super loadView];NSLog(@"%s", __func__);
}
- (void)viewWillAppear:(BOOL)animated {NSLog(@"%s", __func__);
}
- (void)viewWillLayoutSubviews {NSLog(@"%s", __func__);
}
- (void)viewDidLayoutSubviews {NSLog(@"%s", __func__);
}
- (void)viewDidAppear:(BOOL)animated {NSLog(@"%s",__func__);
}
- (void)viewWillDisappear:(BOOL)animated {NSLog(@"%s", __func__);
}
- (void)viewDidDisappear:(BOOL)animated {NSLog(@"%s", __func__);
}
/*
#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {// Get the new view controller using [segue destinationViewController].// Pass the selected object to the new view controller.
}
*/@end

運行結果

1.present和dismiss

請添加圖片描述

下面是函數打印的結果

請添加圖片描述

在這里就是這樣一個順序,就是先執行loadview這一步把View載入到內存中,然后再用viewDidload這個方法把控件加載到view上,然后就是調用viewwilllayoutsubviewviewdidlayoutsubview這兩個方法來進行布局,最后會執行 viewdidappear 這個方法完成所有視圖的加載。

這是彈出的部分,在后面我們把 push 和 pop 這一對展示完后我會去結合 present 和 dismis解釋視圖消失相關的內容。

2.push和pop

請添加圖片描述

代碼和上面相同

下面是打印結果

請添加圖片描述

在這里我去著重介紹一下他的消失順序,push 和 pop 的消失與 present 和 dismiss 的消失最大的不同就是push 中的 viewDidDisappear 是在下一個視圖的 viewDidAppear 之前的然而你像在 present 中 viewDidDisappear是在下一個視圖 viewDidAppear 之后的。

在這里最重要的原因就是

  • 因為 push 是棧結構,A 被“擠下去”,所以它會走消失的生命周期。
  • B 被放在最頂上,執行“將要出現”和“已經出現”。
  • present 時,B 的 didAppear 在 A 的 didDisappear 之前執行
  • 也就是說,新控制器(B)已經展示成功了,舊控制器(A)才真正被認為消失。
  • 這是因為 present 是模態展示,A 并沒有被銷毀,只是被 B 遮擋了,系統優先保證 B 先可見。

三、總結

init / loadView -> viewDidLoad -> viewWillAppear -> viewDidAppear
-> viewWillDisappear -> viewDidDisappear -> dealloc

這就是一個非常簡單的流程圖他也展示了UIViewController 的生命周期。

在這里我想補充一點就是

- (void)loadView {[super loadView];NSLog(@"%s", __func__);
}

在這之中我們必須要使用**[super loadView]**因為這樣他就可以幫助我們自動生成 View。如果我們找不到 View,程序就會一直調用loadView方法來尋找。

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

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

相關文章

第30章 零售與電商AI應用

本章將深入探討人工智能在零售與電商領域的革命性應用。我們將從智能推薦系統、動態定價、庫存管理到創新的虛擬試衣間,全面解析AI如何重塑購物體驗和商業運營效率,并為每個關鍵技術點提供代碼實戰,幫助你掌握將AI應用于真實商業場景的能力。…

QT通過QModbusRtuSerialMaster讀寫電子秤數據實例

一、電子稱常用功能:稱重、清零、去皮;電子秤的通訊方式:Modbus通信、串口通信。二、QT讀寫電子秤軟件界面如下:三、核心代碼如下:.pro項目文件代碼:QT core gui serialbus serialport.h頭文件代碼#…

sqlmap常用命令

ZZHow(ZZHow1024) 一、掃描注入點 1.GET方法,給URL: #探測該url是否存在漏洞 python sqlmap.py -u "http://192.168.10.1/sqli/Less-1/?id1"#如果我們已經知道admin這里是注入點的話,可以在其后面加個*來讓sqlmap對其注入 python …

JVM如何排查OOM

當JVM(Java虛擬機)出現OOM(OutOfMemoryError)時,可以按照以下步驟和方法,用于幫助定位和解決JVM中的OOM問題1.查看異常堆棧信息查看異常堆棧信息(StackTrace)是定位問題的關鍵。OOM異…

存算一體芯片生態評估:從三星PIM到知存科技WTM2101

點擊 “AladdinEdu,同學們用得起的【H卡】算力平臺”,注冊即送-H卡級別算力,80G大顯存,按量計費,靈活彈性,頂級配置,學生更享專屬優惠。 引言:存算一體技術的崛起與意義 在傳統馮諾…

[數據結構] 棧 · Stack

一.棧 stack 1.概念 棧 : 一種特殊的線性表 , 其只允許再固定的一段進行插入和刪除元素操作 進行數據插入和刪除操作的一段稱為 棧頂 ; 另一端稱為棧底棧中的數據元素遵循 先進后出 原則(LIFO)壓棧 : 棧的插入操作叫做 進棧 或 壓棧 或 入棧 , 入數據在棧頂出棧 : 棧的刪除…

MySQL執行過程中如何選擇最佳的執行路徑

本篇文章介紹一個非常核心的數據庫問題。MySQL 選擇最佳執行路徑(即“查詢優化”)的過程是由其查詢優化器(Query Optimizer) 完成的。 簡單來說,優化器的目標是:在多種可能的執行方案中,選擇一個…

【設計模式】從游戲角度開始了解設計模式 --- 抽象工廠模式

永遠記住,你的存在是有意義的, 你很重要, 你是被愛著的, 而且你為這個世界帶來了無可取代的東西。 -- 麥克西 《男孩、鼴鼠、狐貍和馬》-- 從零開始了解設計模式抽象工廠模式抽象工廠模式 今天我們一起來探究抽象工廠模式&#x…

tensorflow.js 使用場景

TensorFlow.js (簡稱 TF.js) 是一個利用 WebGL 和 Node.js 在瀏覽器和服務器端進行機器學習模型訓練和部署(推理)的 JavaScript 庫。它的核心價值在于將機器學習的能力帶入了 Web 開發者和 JavaScript 生態的領域。 其主要應用場景可以分為以下幾大類: 一、在瀏覽器中直接進…

詳解mcp以及agen架構設計與實現

文章目錄1.MCP概念2.MCP服務端主要能力3.MCP技術生態4.MCP與Function call區別5.MCP生命周期6.MCP java SDK7.MCP應用場景8.基于springAIollma阿里qianwenmcp設計私有AIAgent應用實現9.AI java項目落地技術選型10.構建AI Agent四大模塊11.LLM(大模型)與MCP之間關系12.A2A、MCP、…

六級第一關——下樓梯

上目錄: 目錄 題目描述 輸入格式 輸出格式 輸入輸出樣例 說明/提示 一、DP的意義以及線性動規簡介 在一個困難的嵌套決策鏈中,決策出最優解。 二、動態規劃性質淺談 三、子序列問題 (一)一個序列中的最長上升子序列&am…

【Linux基礎】Linux系統配置IP詳解:從入門到精通

目錄 1 Linux網絡配置概述 2 網卡配置文件位置和命名規則 2.1 配置文件位置 2.2 網卡命名規則 2.3 配置文件命名示例 3 網卡配置文件詳解 3.1 主要參數說明 4 Linux系統配置IP步驟 4.1 DHCP動態配置 4.2 靜態IP配置 5 Linux網絡配置流程 5.1 網絡配置流程 5.2 網卡…

C語言sprintf的高效替代方案

C語言的sprintf和snprintf將變量格式化輸出到內存buffer,其功能強大,用起來很方便。但sprintf系列函數的運行效率低下,主要包括四方面的原因:格式字符串解析、變參處理、locale(本地化)支持和通用&#xff…

【知識堂】制造業與物流數字化全景圖:系統縮寫大全與專業名詞速查手冊

前言在制造業和物流行業的數字化轉型過程中,我們經常會接觸到大量的 系統縮寫(如 ERP、MES、WMS…)和 專業名詞(如 AGV、BOM、LOT…)。 這些縮寫往往讓剛入行的人“一頭霧水”,即使是有經驗的從業者&#x…

利用JSONCrack與cpolar提升數據可視化及跨團隊協作效率

文章目錄前言1. 在Linux上使用Docker安裝JSONCrack2. 安裝Cpolar內網穿透工具3. 配置JSON Crack界面公網地址4. 遠程訪問 JSONCrack 界面5. 固定 JSONCrack公網地址前言 JSONCrack 是一款功能強大的開源數據可視化工具,專為解析和展示復雜的 JSON、XML 等結構化數據…

CANoe入門之一 CANoe功能概述

01 CANoe功能概述 CANoe軟件在汽車電子領域被廣泛應用。 CANoe軟件的全稱是CAN Open Environment,它是一個專業的系統級總線和ECU仿真、分析、開發、測試工具。支持ECU或總線網絡開發從需求分析到系統實現的全過程,包括模型創建、仿真、測試、診斷及通信…

項目管理核心八項(軟件篇)

2025年09月11日23:50:33:進來常思,寫代碼也五六年了,后面的路該何去何從呢? 項目管理核心八項一、項目管理之“建立開發人員 backup 機制”二、待補充一、項目管理之“建立開發人員 backup 機制” “建立開發人員 backup 機制” 是…

springboot redisson 分布式鎖入門與實戰

Spring Boot3 Redisson 項目地址 https://gitee.com/supervol/loong-springboot-study (記得給個start,感謝) Redisson 介紹 在分布式系統中,多節點部署的應用對共享資源(如數據庫記錄、緩存鍵、文件)的…

使用 Tkinter + Requests 實現地理信息安全系統學習時長助手

?重磅!盹貓的個人小站正式上線啦~誠邀各位技術大佬前來探秘!? 這里有: 硬核技術干貨:編程技巧、開發經驗、踩坑指南,帶你解鎖技術新姿勢!趣味開發日常:代碼背后的腦洞故事、工具…

構建一個優雅的待辦事項應用:現代JavaScript實踐

構建一個優雅的待辦事項應用:現代JavaScript實踐本文將介紹如何使用現代JavaScript(ES6)和DOM操作創建一個功能完整的待辦事項應用,無需任何外部庫或框架。功能概述添加新任務標記任務為完成/未完成編輯任務內容刪除任務過濾任務&…