清晰的理解它们能帮你更好地管理应用状态和资源。
一、iOS 应用(App)生命周期
应用生命周期描述了 App 从启动到终止的整个过程,由UIApplicationDelegate(应用代理)来管理。
核心阶段与代理方法(按执行顺序)
swift
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
// 1. App启动完成(最核心的入口)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
print("应用启动完成 - didFinishLaunchingWithOptions")
// 通常在这里初始化根视图控制器、配置全局设置等
return true
}
// 2. App即将进入前台(还未激活,可做界面刷新)
func applicationWillEnterForeground(_ application: UIApplication) {
print("即将进入前台 - applicationWillEnterForeground")
}
// 3. App已进入前台并激活(用户可交互)
func applicationDidBecomeActive(_ application: UIApplication) {
print("已激活 - applicationDidBecomeActive")
// 恢复定时器、重新开始播放音频、刷新数据等
}
// 4. App即将进入后台(用户按Home键/切换App)
func applicationWillResignActive(_ application: UIApplication) {
print("即将失活 - applicationWillResignActive")
// 暂停定时器、保存临时数据、暂停音频播放等
}
// 5. App已进入后台
func applicationDidEnterBackground(_ application: UIApplication) {
print("已进入后台 - applicationDidEnterBackground")
// 持久化数据、释放不必要的资源(有大约5秒时间,耗时操作需申请后台任务)
}
// 6. App即将终止(仅在后台时可能触发,如系统回收内存)
func applicationWillTerminate(_ application: UIApplication) {
print("即将终止 - applicationWillTerminate")
// 最终的资源清理、数据保存
}
}
关键说明
- 启动流程 :用户点击 App 图标 → 系统加载可执行文件 → 调用
didFinishLaunchingWithOptions→ 显示界面 → 进入活跃状态。 - 后台与前台切换 :活跃 → 失活(
WillResignActive)→ 后台(DidEnterBackground)→ 前台(WillEnterForeground)→ 活跃(DidBecomeActive)。 - 终止 :后台状态下系统回收内存,触发
applicationWillTerminate(若 App 在前台,直接终止,不触发此方法)。
二、UIViewController 生命周期
视图控制器是管理 UIView 的核心,其生命周期围绕视图的创建、显示、隐藏、销毁展开,是 iOS 开发中最常接触的生命周期。
核心方法(按执行顺序)
swift
import UIKit
class ViewController: UIViewController {
// 1. 初始化(创建VC对象)
init?(coder: NSCoder) {
super.init(coder: coder)
print("1. 初始化 - init")
// 初始化非UI相关的属性
}
// 2. 加载视图(首次访问view属性时触发)
override func loadView() {
super.loadView()
print("2. 加载视图 - loadView")
// 手动创建view(若不重写,系统会加载storyboard/xib的view)
self.view = UIView(frame: UIScreen.main.bounds)
self.view.backgroundColor = .white
}
// 3. 视图加载完成(view已创建完成)
override func viewDidLoad() {
super.viewDidLoad()
print("3. 视图加载完成 - viewDidLoad")
// 初始化UI控件、绑定数据、添加监听(只执行一次)
}
// 4. 视图即将布局子视图(view的bounds变化时触发,如旋转屏幕)
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
print("4. 视图即将布局子视图 - viewWillLayoutSubviews")
// 调整控件布局(执行多次)
}
// 5. 视图已布局子视图
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
print("5. 视图已布局子视图 - viewDidLayoutSubviews")
// 获取控件最终的frame(执行多次)
}
// 6. 视图即将显示在屏幕上(每次显示都触发,如push/pop后重新显示)
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
print("6. 视图即将显示 - viewWillAppear")
// 刷新数据、开始动画、注册通知等
}
// 7. 视图已显示在屏幕上
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print("7. 视图已显示 - viewDidAppear")
// 启动定时器、请求网络数据、播放视频等
}
// 8. 视图即将从屏幕上消失
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
print("8. 视图即将消失 - viewWillDisappear")
// 暂停动画、移除通知、保存数据等
}
// 9. 视图已从屏幕上消失
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
print("9. 视图已消失 - viewDidDisappear")
// 释放不必要的资源(如图片缓存)
}
// 10. 内存警告(系统内存不足时触发)
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
print("10. 内存警告 - didReceiveMemoryWarning")
// 释放缓存、非必要的视图等
}
// 11. 视图控制器销毁(deinit)
deinit {
print("11. 视图控制器销毁 - deinit")
// 最终的资源释放(如移除监听、取消网络请求)
}
}
关键说明
- 核心流程:初始化 → 加载视图 → 视图加载完成 → 布局子视图 → 即将显示 → 已显示 → 即将消失 → 已消失 → 销毁。
- viewDidLoad :只执行一次,适合做一次性初始化;viewWillAppear/viewDidAppear:每次显示都执行,适合刷新动态数据。
- 内存警告 :
didReceiveMemoryWarning中需主动释放非必要资源,避免 App 被系统杀死。 - deinit:只有当 VC 的引用计数为 0 时才会触发,需确保无循环引用(如闭包未捕获 self 为 weak/unowned)。
三、UIView 生命周期
UIView 的生命周期依附于视图控制器,核心是 "创建 - 布局 - 绘制 - 销毁",重点关注布局和绘制相关方法。
核心阶段与方法
swift
import UIKit
class CustomView: UIView {
// 1. 初始化(创建View)
override init(frame: CGRect) {
super.init(frame: frame)
print("1. View初始化 - init(frame:)")
// 设置默认属性(如背景色、圆角)
self.backgroundColor = .lightGray
}
required init?(coder: NSCoder) {
super.init(coder: coder)
print("1. View初始化 - init(coder:)")
}
// 2. 准备布局(iOS 6+,替代autoresizingMask)
override func prepareForLayout() {
super.prepareForLayout()
print("2. 准备布局 - prepareForLayout")
// 布局前的准备工作(如设置约束优先级)
}
// 3. 布局子视图(bounds变化时触发,如frame、center修改)
override func layoutSubviews() {
super.layoutSubviews()
print("3. 布局子视图 - layoutSubviews")
// 手动调整子视图frame(若不用AutoLayout)
for subview in self.subviews {
subview.center = self.center
}
}
// 4. 绘制内容(首次显示/setNeedsDisplay()触发)
override func draw(_ rect: CGRect) {
super.draw(rect)
print("4. 绘制内容 - draw(_:)")
// 手动绘制图形(如绘制线条、文字)
let context = UIGraphicsGetCurrentContext()
context?.setStrokeColor(UIColor.red.cgColor)
context?.stroke(CGRect(x: 10, y: 10, width: 100, height: 100))
}
// 5. 即将添加到父视图
override func willMove(toSuperview newSuperview: UIView?) {
super.willMove(toSuperview: newSuperview)
print("5. 即将添加到父视图 - willMove(toSuperview:)")
// 父视图变化前的处理
}
// 6. 已添加到父视图
override func didMoveToSuperview() {
super.didMoveToSuperview()
print("6. 已添加到父视图 - didMoveToSuperview")
// 父视图变化后的处理(如根据父视图调整自身大小)
}
// 7. 即将添加到窗口
override func willMove(toWindow newWindow: UIWindow?) {
super.willMove(toWindow: newWindow)
print("7. 即将添加到窗口 - willMove(toWindow:)")
}
// 8. 已添加到窗口
override func didMoveToWindow() {
super.didMoveToWindow()
print("8. 已添加到窗口 - didMoveToWindow")
// 只有添加到window后,View才会真正显示在屏幕上
}
// 9. 销毁(deinit)
deinit {
print("9. View销毁 - deinit")
// 释放View相关资源(如移除子视图、取消动画)
}
}
关键说明
- layoutSubviews:最常用的方法,每次 View 的尺寸变化都会触发,适合手动调整子视图布局(若使用 AutoLayout,系统会自动处理,无需重写)。
- draw(_:) :仅在需要手动绘制内容时重写,避免在其中做耗时操作(会影响渲染性能);调用
setNeedsDisplay()可触发重新绘制。 - Window 关联 :View 只有添加到
UIWindow(应用的主窗口)后,才会被渲染并显示在屏幕上;didMoveToWindow是 View 真正 "可见" 的标志。 - 销毁 :当 View 从父视图移除且无强引用时,
deinit触发,需确保子视图也被正确释放。
总结
- 应用生命周期 :全局层面,管理 App 从启动到终止的状态,核心是
UIApplicationDelegate的代理方法,关注前台 / 后台切换和资源保存。 - 视图控制器生命周期 :页面层面,核心是
viewDidLoad(一次性初始化)、viewWillAppear(每次显示刷新)、deinit(资源释放),是业务逻辑的主要载体。 - 视图生命周期 :控件层面,依附于 VC,核心是
layoutSubviews(布局)和draw(_:)(绘制),关注控件尺寸调整和视觉渲染。
三者的关联:App 启动后创建根 VC → VC 创建并加载 View → View 添加到 Window 显示 → App 进入前台活跃状态;App 进入后台时,VC 的 View 会被隐藏,资源可按需释放。