iOS App 生命周期:UIWindowSceneDelegate 流程与 UIApplicationDelegate 流程对照
基于 Scene-based 流程与传统 UIApplicationDelegate 流程实测整理。测试机型与系统版本:iPhone 17 Pro / iOS 26.5(Scene)。图中为方法名简写。
下文「Scene 时序」对应 UIWindowSceneDelegate(及 Scene 下仍走 UIApplicationDelegate 的部分回调);「App 时序」对应未启用 Scene 时的传统 UIApplicationDelegate 流程。
第一部分:Scene 时序(UIWindowSceneDelegate)
1.1 冷启动
普通冷启与 URL Scheme / Universal Link 时序相同,差别只在 willConnectTo 的 connectionOptions(UIScene.ConnectionOptions)及其属性:
- 普通冷启:
connectionOptions为空(各属性均无值) - 点击 URL Scheme:
connectionOptions.urlContexts(Set<UIOpenURLContext>),内含打开 App 的 URL - 点击 Universal Link:
connectionOptions.userActivities(Set<NSUserActivity>),内含 Universal Link 对应的 user activity - 点击非静默通知:
connectionOptions.notificationResponse(UNNotificationResponse),即用户点击该通知的响应对象;随后还会走didReceive - 静默 Push:
connectionOptions无通知相关属性有值,随后走didReceiveRemoteNotification
冷启时 URL Scheme / Universal Link 通常不再回调对应 Scene 入口方法,需在 willConnectTo 自行取出。
补充几点与通知相关的冷启行为:
- 非静默通知无法在未点击时冷启唤醒app
- 静默走
UIApplicationDelegate的didReceiveRemoteNotification,不走UNUserNotificationCenter点击回调 - 静默 Push 冷启到
didReceiveRemoteNotification即止,不会再调用sceneWillEnterForeground/sceneDidBecomeActive等前台生命周期方法
1.2 前后台与系统权限弹窗
1.3 非静默远程通知
- 前台收到非静默通知:走
willPresent- 有无授权都会回调
- 未授权时不进通知栏、无声音
- 「点击通知」依赖通知栏展示,需已授权
- 后台收到后若不点通知、只是普通回前台:只有前后台生命周期回调,无通知相关回调
- 点击通知回前台:
didReceive发生在sceneWillEnterForeground之前
1.4 静默远程通知
静默通知走 UIApplicationDelegate 的 didReceiveRemoteNotification,与 UNUserNotificationCenter 的 willPresent / didReceive 不是同一条路径。
- 前台收到静默通知:走
didReceiveRemoteNotification(有无授权都会回调) - 后台收到静默通知后回前台(已授权):后台即可收到
didReceiveRemoteNotification;随后用户回前台再走前后台生命周期 - 后台收到静默通知后回前台(未授权):时序与已授权相同,后台即可收到
didReceiveRemoteNotification,不必先回前台
1.5 后台点击 URL Scheme / Universal Link
前提:App 已在后台(并非冷启)。用户点击 URL Scheme 或 Universal Link,把 App 从后台带回前台:
- 点击 URL Scheme:
openURLContexts在sceneWillEnterForeground之前 - 点击 Universal Link:
continue在WillEnterForeground之后、DidBecomeActive之前
第二部分:App 时序(UIApplicationDelegate)
2.1 冷启动
- 非静默无法在未点击时冷启唤醒app
- 静默 Push 冷启到
didReceiveRemoteNotification即止,不会再调用applicationDidBecomeActive等前台生命周期方法
2.2 前后台与系统权限弹窗
2.3 非静默远程通知
- 前台收到非静默通知:走
willPresent- 有无授权都会回调
- 未授权时不进通知栏、无声音
- 「点击通知」依赖通知栏展示,需已授权
- 后台收到后若不点通知、只是普通回前台:只有前后台生命周期回调,无通知相关回调
- 点击通知回前台:
didReceive发生在applicationWillEnterForeground之后、DidBecomeActive之前
2.4 静默远程通知
静默通知走 UIApplicationDelegate 的 didReceiveRemoteNotification,不走 UNUserNotificationCenter 的 willPresent / didReceive。
- 前台收到静默通知:走
didReceiveRemoteNotification(有无授权都会回调) - 后台收到静默通知后回前台(已授权):后台即可收到
didReceiveRemoteNotification;随后用户回前台再走前后台生命周期 - 后台收到静默通知后回前台(未授权):需先回前台,
applicationDidBecomeActive之后才收到didReceiveRemoteNotification
2.5 后台点击 URL Scheme / Universal Link
前提:App 已在后台(并非冷启)。用户点击 URL Scheme 或 Universal Link,把 App 从后台带回前台:
- 点击 URL Scheme:
openURL在WillEnterForeground之后、DidBecomeActive之前 - 点击 Universal Link:
continueUserActivity同样在WillEnterForeground之后、DidBecomeActive之前
第三部分:两种流程差异
左列为 UIApplicationDelegate 流程,右列为 UIWindowSceneDelegate 流程(Scene-based)。只对比非显而易见的行为差异:例如同名职责方法从 application* 换成 scene*、以及 Scene 流程多出的 willConnectTo 本身,都不单独拿出来讲。红框标出真正需要注意的不同点。
3.1 普通冷启
UIWindowSceneDelegate 冷启多一次 WillEnterForeground。
3.2 Scheme 冷启
- 入口参数载体不同。使用 UIWindowSceneDelegate 时,launchOptions 为空,相关参数放在 connectionOptions 中
UIApplicationDelegate会调用openURL,UIWindowSceneDelegate不会。
3.3 Universal Link 冷启
- 入口参数载体不同。使用 UIWindowSceneDelegate 时,launchOptions 为空,相关参数放在 connectionOptions 中
UIApplicationDelegate会调用continueUserActivity,UIWindowSceneDelegate不会。
3.4 后台点击 Scheme
openURL / openURLContexts 相对 WillEnterForeground 的时机: UIApplicationDelegate 在后,UIWindowSceneDelegate 在前。
3.5 后台点击非静默通知回前台
didReceive 相对 WillEnterForeground 的时机: UIApplicationDelegate 在后,UIWindowSceneDelegate 在前。
3.6 静默 Push 冷启
UIApplicationDelegate 的 launchOptions 带通知信息;UIWindowSceneDelegate 的 connectionOptions 无通知信息,静默 payload 仍通过 didReceiveRemoteNotification 传入。
3.7 后台静默通知(未授权)
未授权时,UIApplicationDelegate 回前台后才收到静默回调;UIWindowSceneDelegate 不用回前台,后台也能收到静默回调。
3.8 未授权时静默 Push 能否冷启
未授权时:UIApplicationDelegate 流程无法唤醒 App;UIWindowSceneDelegate 流程可以冷启唤醒,并走静默冷启链路。