UIKit:冷启动时从AppDelegate调用视图控制器中的函数
如何在ViewController中检测应用冷启动并在viewDidAppear前执行对应函数
原代码的核心问题是:application(_:didFinishLaunchingWithOptions:)执行时,目标ViewController还未完成初始化,appLaunchDelegate此时为nil,导致appDidLaunchFromColdStart()无法被调用。因为viewDidLoad要等到ViewController加载后才会执行,这时候已经错过了冷启动检测的时机。
下面提供两种可行的解决方案:
方案一:通过AppDelegate存储冷启动状态,在ViewController初始化阶段读取
这种方式实现简单,适合单一页面需要冷启动逻辑的场景:
- 在AppDelegate中添加静态属性存储冷启动状态
- 在冷启动触发时标记状态
- 在ViewController初始化时读取状态并执行逻辑
import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? // 静态属性存储冷启动状态 static var isColdLaunch = false func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // 判定冷启动:launchOptions的source为空即为冷启动 AppDelegate.isColdLaunch = launchOptions?[.source] == nil // 设置根视图控制器(若项目中未自动配置) window = UIWindow(frame: UIScreen.main.bounds) window?.rootViewController = YourViewController() window?.makeKeyAndVisible() return true } } class YourViewController: UIViewController { override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) // 初始化时检查冷启动状态 checkColdLaunch() } required init?(coder: NSCoder) { super.init(coder: coder) checkColdLaunch() } private func checkColdLaunch() { guard AppDelegate.isColdLaunch else { return } // 执行冷启动专属逻辑 print("冷启动逻辑在ViewController初始化时执行(早于viewDidAppear)") // 重置状态,避免后续重复触发 AppDelegate.isColdLaunch = false } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) print("viewWillAppear执行") } }
方案二:使用通知中心触发冷启动回调
这种方式扩展性强,适合多个页面需要监听冷启动事件的场景:
- 自定义冷启动通知名称
- 检测到冷启动时发送通知
- 在ViewController初始化阶段注册通知监听
import UIKit // 自定义通知名称 extension Notification.Name { static let appDidColdLaunch = Notification.Name("appDidColdLaunch") } @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { if launchOptions?[.source] == nil { // 发送冷启动通知 NotificationCenter.default.post(name: .appDidColdLaunch, object: nil) } window = UIWindow(frame: UIScreen.main.bounds) window?.rootViewController = YourViewController() window?.makeKeyAndVisible() return true } } class YourViewController: UIViewController { override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) registerColdLaunchNotification() } required init?(coder: NSCoder) { super.init(coder: coder) registerColdLaunchNotification() } private func registerColdLaunchNotification() { // 注册通知,用main队列保证UI操作安全 NotificationCenter.default.addObserver(forName: .appDidColdLaunch, object: nil, queue: .main) { [weak self] _ in self?.handleColdLaunch() } } private func handleColdLaunch() { print("冷启动逻辑在通知回调中执行(早于viewDidAppear)") // 这里写入你的业务逻辑 } deinit { // 移除通知监听,防止内存泄漏 NotificationCenter.default.removeObserver(self) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) print("viewWillAppear执行") } }
方案对比
- 方案一:代码简洁,状态管理直接,适合单一页面的冷启动需求。
- 方案二:支持多页面监听,扩展性好,适合复杂应用场景。
内容的提问来源于stack exchange,提问作者user20053202
相关产品推荐
相关产品推荐

