深度解析iOS應用程式的生命周期

2021-02-13 CSDN

iOS應用程式一般都是由自己編寫的代碼和系統框架(system frameworks)組成,系統框架提供一些基本infrastructure給所有App來運行,而你提供自己編寫的代碼來定製App的外觀和行為。因此,了解iOS Infrastructure和它們如何工作對編寫App是很有幫助的。


Main函數入口

所有基於C編寫的App的入口都是main函數,但iOS應用程式有點不同。不同就是你不需要為iOS應用程式而自己編寫main函數,當你使用Xcode創建工程的時候就已經提供了。除非一些特殊情況,否則你不應該修改Xcode提供的main函數實現。示例代碼如下:

[cpp] view plaincopy

#import <UIKit/UIKit.h>

#import "AppDelegate.h"

int main(int argc, char * argv[])

{

@autoreleasepool {

return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

}

}

上面實例代碼中有一個很重要的函數UIApplicationMain,它主要是創建App的幾個核心對象來處理以下過程:

從可用Storyboard文件加載用戶界面;

調用AppDelegate自定義代碼來做一些初始化設置;

將App放入Main Run Loop環境中來響應和處理與用戶交互產生的事件。

應用程式的架構

iOS應用程式都遵循Model-View-Controller的架構,Model負責存儲數據和處理業務邏輯,View負責顯示數據和與用戶交互,Controller是兩者的中介,協調Model和View相互協作。它們的通訊規則如下:

Controller能夠訪問Model和View,Model和View不能互相訪問。


2. 當View與用戶交互產生事件時,使用target-action方式來處理。


3. 當View需要處理一些特殊UI邏輯或獲取數據源時,通過delegate或data source方式交給Controller來處理。


4. Model不能直接與Controller通信,當Model有數據更新時,可以通過Notification或KVO (Key Value Observing)來通知Controller更新View。


了解iOS的MVC設計模式之後,我們從下圖來了解在MVC模式下iOS應用程式有哪些關鍵對象以及它們職責主要是什麼?


用戶與iOS設備交互時產生的事件(Multitouch Events,Motion Event,Remote Control Event)交由UIApplication對象來分發給control objects(UIControl)對應的target objects來處理並且管理整個事件循環,而一些關於App運行時重要事件委託給app delegate來處理。

App delegate對象遵循UIApplicationDelegate協議,響應app運行時重要事件(app啟動、app內存不足、app終止、切換到另一個app、切回app),主要用於app在啟動時初始化一些重要數據結構;例如,初始化UIWindow,設置一些屬性,為window添加rootViewController。

View Controller有一個view屬性是view層次結構中的根view,你可以添加子view來構建複雜的view;controller有一些viewDidLoad、viewWillAppear等方法來管理view的生命周期;由於它繼承UIResponder,所有還會響應和處理用戶事件。

data model對象主要用來存儲數據。例如,餓了麼app在搜索切換地址後,有歷史記錄搜索地址歷史,當app下次啟動時,讀取和顯示搜索地址歷史。

document對象(繼承UIDocument)用來管理一些或所有的data model對象。document對象並不是必須的,但提供一種方便的方式來分組屬於單個文件或多個文件的數據。

UIWindow對象位於view層次結構中的最頂層,它充當一個基本容器而不顯示內容,如果想顯示內容,添加一個content view到window。

它也是繼承UIResponder,所以它也是會響應和處理用戶事件。

View對象可以通過addSubview和removeFromSuperview 等方法管理view的層次結構,使用layoutSubviews、layoutIfNeeded和setNeedsLayout等方法布局view的層次結構,當你發現系統提供view已經滿足不了你想要的外觀需求時,可以重寫drawRect方法或通過layer屬性來構造複雜的圖形外觀和動畫。還有一點,UIView也是繼承UIResponder,所以也能夠處理用戶事件。

Control對象通常就是處理特定類型用戶交互的View,常用的有button、switch、text field等。

除了使用View和Control來構建view層次結構來影響app外觀之外,還可以使用Core Animation框架的Layer對象來渲染view外觀和構建複雜的動畫。

Main Run Loop

一個iOS應用程式的main run loop主要作用是處理所有與用戶相關的事件。UIApplication對象在啟動時就設置main run loop和使用它來處理事件和更新基於view的界面。正如它的名字顯示,main run loop是運行在應用程式的主線程。這樣就確保與接收到用戶相關的事件被有序地處理。

下圖顯示main run loop的架構和用戶事件最終是怎樣被應用程式處理。當用戶與設備交互時,系統就會生成與交互關聯的事件,然後被應用程式的UIKit通過一個特殊的埠來分發。應用程式把事件放入隊列,然後逐個分發到main run loop來執行。UIApplication對象是第一個對象接收到事件,然後決定怎樣處理它。一個touch event通常都被分發到main window對象,然後依次分發到發生觸碰的view。其他event的接收事件對象路徑可能有點不同。


大多數的事件通過使用main run loop來分發,但有些不是。有些事件被發送到一個delegate對象或傳遞到你提供的block中。想了解更多如何處理大多數類型的事件,其中包括touch、remote control、motion、accelerometer和gyroscopic等事件,請查閱Event Handle Guide for iOS。

應用程式的狀態和多任務

有時系統會從App一種狀態切換另一種狀態來響應系統發生的事件。例如,當用戶按下Home鍵、電話打入或其他中斷發生時,當前運行的應用程式會切換狀態來響應。應用程式的狀態有以下幾種:


Not running:App還沒運行

Inactive:App運行在foreground但沒有接收事件

Active:App運行在foreground和正在接收事件

Background:運行在background和正在執行代碼

Suspended:運行在background但沒有執行代碼

大多數發生狀態轉換時都會調用delegate對象對應的方法來響應App的狀態改變。下面匯總了delegate對象的所有方法,當App狀態發生轉換時,你可能會使用到它們。

application:willFinishLaunchingWithOptions: - 這個方法是你在啟動時的第一次機會來執行代碼

application:didFinishLaunchingWithOptions: - 這個方法允許你在顯示app給用戶之前執行最後的初始化操作

applicationDidBecomeActive: - app已經切換到active狀態後需要執行的操作

applicationWillResignActive: - app將要從前臺切換到後臺時需要執行的操作

applicationDidEnterBackground: - app已經進入後臺後需要執行的操作

applicationWillEnterForeground: - app將要從後臺切換到前臺需要執行的操作,但app還不是active狀態

applicationWillTerminate: - app將要結束時需要執行的操作

現在講下App啟動、來回切換App和鎖屏時狀態的切換和調用對應哪些delegate對象的方法:


如圖所示,當App啟動時,首先由not running狀態切換到inactive狀態,此時調用application:didFinishLaunchingWithOptions:方法;然後由inactive狀態切換到active狀態,此時調用applicationDidBecomeActive:方法。


當App發生中斷時,由active狀態切換到inactive狀態,此時調用applicationWillResignActive:方法。


如圖所示,當切換到另一個App時,由狀態active切換到inactive,此時調用applicationWillResignActive:方法;然後從inactive狀態切換到running狀態,此時調用applicationDidEnterBackground:方法。


而當切換回本來的App時,由running狀態切換到inactive狀態,此時調用applicationWillEnterForeground:方法,然後由inactive狀態切換到active狀態,調用applicationDidBecomeActive:方法。


如何所示,當手機鎖屏時,由狀態active切換到inactive,此時調用applicationWillResignActive:;然後再由inactive狀態切換到running狀態,此時調用applicationDidEnterBackground:方法。

更多關於app狀態切換以及調用app delegate哪些方法,請觀看WWDC 2011 Session的session_320__adopting_multitasking_in_your_app視頻。

應用程式的終止

系統常常是為其他app啟動時由於內存不足而回收內存最後需要終止應用程式,但有時也會是由於app很長時間才響應而終止。如果app當時運行在後臺並且沒有暫停,系統會在應用程式終止之前調用applicationWillTerminate:來保存用戶的一些重要數據以便下次啟動時恢復到app原來的狀態。

總結

本文總結了iOS應用程式從啟動到結束過程中有哪些關鍵對象在參與,以及當用戶與系統交互時產生事件時,系統利用main run loop來管理事件循環,決定將事件交給系統哪些對象處理和如何處理。而當App啟動、來回切換App和鎖屏時,App的狀態如何切換和調用對應的哪些app delegate對象來處理。

擴展閱讀

App Programming Guide for iOS

Developing iOS 7 App for iPhone and iPad

深入理解RunLoop

Objective-C Autorelease Pool 的實現原理

作者簡介:劉耀柱(@Sam_Lau_Dev),iOS Developer兼業餘Designer,參與開發技術前線iOS項目翻譯,個人博客:http://www.jianshu.com/users/256fb15baf75/latest_articles,GitHub:https://github.com/samlaudev

本文為CSDN原創,點擊「閱讀原文」可查看全文並參與討論。

如果您喜歡這篇文章,請點擊右上角「…」將本文分享給你的朋友。

相關焦點

  • 小程序生命周期
    生命周期1.1 什麼是生命周期?「生命周期就是指一個對象的生老病死。基本涵義可以通俗地理解為「從搖籃到墳墓」(Cradle-to-Grave)的整個過程。小程序生命周期【點擊放大】1.2 用途在技術中心,我們可以理解生命周期為從一個應用從創建到銷毀的過程。
  • 【iOS取證】應用快照
    下面我們就來看看應用快照的提取和解析。首先我們需要確定其存儲路徑,經過實驗(筆者測試了iPhone X,iOS13.3.1和iPhone 6,iOS12.4.4)發現應用快照的存儲路徑位於應用程式沙盒中的Library文件夾下,12.4.4版本和13.3.1版本的存儲路徑略微有差別,這也導致同樣的提取方式,不同的效果。
  • iOS取證之應用快照
    下面我們就來看看應用快照的提取和解析。首先我們需要確定其存儲路徑,經過實驗(筆者測試了iPhone X,iOS13.3.1和iPhone 6,iOS12.4.4)發現應用快照的存儲路徑位於應用程式沙盒中的Library文件夾下,12.4.4版本和13.3.1版本的存儲路徑略微有差別,這也導致同樣的提取方式,不同的效果。
  • 【Android基礎】Activity生命周期
    在Activity中有一些特定的方法稱為生命周期函數(也叫回調函數),這些函數不需要你去調用它,而是會自動的被Android系統調用,Android系統會根據用戶的操作調用這些生命周期函數,比如用戶點擊了應用圖標來啟動應用程式,Android系統就會調用應用程式中主Activity的onCreat()方法,用戶按返回鍵則會觸發onPause()函數,你所需要做的就是利用這些生命周期函數,把你的邏輯寫在恰當的位置
  • iOS線程生命周期的監控
    同時也提供了一套基於C語言的GCD線程池函數庫來支持多線程的處理應用。這些高級的線程類或者函數的內部實現大部分最終都會調用POSIX標準中的pthread線程庫中的pthread_xxx系列函數(#include <pthread.h>)來完成線程的創建、運行、暫停、恢復、銷毀、結束等操作。
  • 2017年排名前11的iOS應用分析工具
    作者丨Emily Goldring譯者丨Teixeira10【譯者注】作者列出了2017排名前11的ios應用分析工具,分別介紹了它們的價格,平臺,特點等,供讀者進行參考和選擇。以下為譯文:似乎每年都有越來越多的移動分析工具,2017年也是如此,所以用戶很難在這麼多iOS應用程式選擇使用哪一個,或者說,用戶將不止使用一個分析工具。開發人員傾向於使用各種分析工具來幫助他們全面了解iOS應用程式,每一個工具都可以為你提供一個獨特的應用程式視圖,以及它的執行情況。
  • iOS開發系列——IOS程序開發概覽「全解析」真正的技術,你值得擁有
    UIApplication對象或子對象;第四個參數是UIApplication的代理類字符串,默認生成的是AppDelegate類,這個類主要用於監聽整個應用程式生命周期的各個事件(其實類似於之前我們文章中提到的事件監聽代理),當UIApplication運行過程中引發了某個事件之後會調用代理中對應的方法;
  • 超深度解析用戶生命周期管理方法論以網際網路金融為例...
    本文結構:全文分為兩大部分:用戶生命周期分析的前置條件、用戶生命周期分析方法論明確用戶生命周期分析的兩個核心目標、四個抓手,同時建立基於用戶生命周期的數據分析體系如何對用戶生命周期價值(LTV)和投資回報率(ROI)進行分解分五個時期詳解各自對應的運營目標和策略,以陸金所、壹錢包、借貸寶、360你財富等各大平臺為例
  • ios12 measure怎麼用 AR測量measure應用使用介紹
    ios12 measure怎麼用?measure應用有什麼用?measure應用暫時只在ios12系統中上線,蘋果商店暫時還沒有measure應用。measure應用在ios12系統的系統程序中可以找到。圖標是一個標尺。ios12 measure應用使用攻略:點擊打開measure應用,可以設置需要測量的物品,設置一個起點,和重點。可獲得測量物品的大小。這就是所謂的AR測量工具。measure應用是蘋果推出的一個新應用,應用了AR技術。
  • 圖解 Laravel 請求的完整生命周期
    通過對其解析,一切都不再那麼神秘,我們會更加自信的構建其應用。Laravel是一套簡潔的PHP Web開發框架(PHP Web Framework),今天,我們就來了解 一下Laravel 的生命周期。在此之前,我們先回顧一下PHP 的生命周期。
  • Jetpack源碼解析---用Lifecycles管理生命周期
    Android_Jetpack組件---Naviagtion源碼解析2. Jetpack源碼解析—Navigation為什麼切換Fragment會重繪?2. 基礎2.1 簡介Lifecycles是一個持有組件生命周期狀態(如Activity、Fragment)信息的類,並允許其他對象觀察此狀態。可以幫助我們方便的管理Activity和Fragment的生命周期。
  • 再談Spring中Bean的生命周期
    網上大部分都是驗證的Bean 在面試問的生命周期,其實查閱JDK還有一個完整的Bean生命周期,這同時也驗證了書是具有片面性的,最fresh 的資料還是查閱原始JDK!!!一、Bean 的完整生命周期在傳統的Java應用中,bean的生命周期很簡單,使用Java關鍵字 new 進行Bean 的實例化,然後該Bean 就能夠使用了。一旦bean不再被使用,則由Java自動進行垃圾回收。
  • 手把手教你搭建能夠實現 Prisma 風格遷移效果的 iOS 酷炫應用
    翻譯 | 廖明月  吳桐  蔡雨萌    整理 |  凡江隨著 2012 年深度神經網絡在 ImageNetchallenge 比賽上以 AlexNet 模型獲勝,深度神經網絡開創了空前的高潮。AI 工程師已經將深度學習技術應用到越來越多的問題域,包括預訓練的深度美國有線電視新聞網模型。還有什麼比創造藝術更富有創造力呢?
  • iOS平臺十大怪異應用程式-iOS,iPhone,iPad,應用程式,蘋果 ——快...
    有些聰明的應用程式能在你的蘋果產品遺失時自動定位,有些能讓你和大洋彼岸的親朋好友們視頻通話。但是下面這些應用從「幫首相完成工作」到「什麼都不幹」真是無奇不有。1、「爺有錢」(I Am Rich,已不可用)
  • PHP高級之一次請求處理過程或生命周期詳解
    Apache啟動後,PHP解釋程序也隨之啟動;PHP的啟動過程有兩步;第一步是初始化一些環境變量,這將在整個SAPI生命周期中發生作用;第二步是生成只針對當前請求的一些變量設置。  一個典型的RSHUTDOWN方法如下:PHP_MSHUTDOWN_FUNCTION(extension_name) {/* Free handlers and persistent memory etc */}  這樣,整個PHP生命周期就結束了
  • 深究Spring中Bean的生命周期
    Springboot啟動原理解析前言這其實是一道面試題,是我在面試百度的時候被問到的,當時沒有答出來(因為自己真的很菜),後來在網上尋找答案,看到也是一頭霧水,直到看到了《Spring in action》這本書,書上有對Bean聲明周期的大致解釋,但是沒有代碼分析,所以就自己上網尋找資料,一定要把這個Bean生命周期弄明白!
  • 你知道Spring是怎麼將AOP應用到Bean的生命周期中的嗎?
    」在上篇文章中(Spring中AOP相關的API及源碼解析,原來AOP是這樣子的)我們已經分析過了AOP的實現的源碼,那麼Spring是如何將AOP應用到Bean的生命周期的呢?這篇文章就帶著大家來探究下這個問題。
  • servlet生命周期
    1.servlet是運行在服務端的java程序2.servlet的生命周期主要有三個方法:init()初始化階段對於tomcat來說,它會將傳遞來的參數放入一個HashTable中,這是一個String-->String[]的鍵值映射終止階段:當web應用被終止,或者Servlet容器終止運行,或者Servlet重新裝載Servlet新實例時,Servlet容器會調用Servlet的destroy
  • G73的宏程序:表達FANUC宏程序深度應用,深孔加工原來是這樣寫的
    >深孔加工G代碼編程與宏語句的對照各變量的介紹,讓了解的更清晰、明了WHILE語句限制循環次數,附各自變量的定義WHILE語句中增加IF語句用法,為鑽孔提供間隙設置在CNC加工中心宏程序的學習過程中,通常因為缺乏相應實例或缺乏相應格式,所以造成無從下手,不知道宏程序是怎麼樣的。
  • Vue.js系列:生命周期鉤子
    開發人員提供了一個Web開發人員可以在Vue.js應用程式的整個生命周期中使用的各種方法的討論。生命周期鉤子是在Vue對象生命周期的某個階段執行的已定義方法。從初始化開始到它被破壞時,對象都會遵循不同的生命階段。這是一個著名的圖表,表示掛鈎順序。讓我們將代碼添加到鉤子並查看它們如何被解僱的階段。<!