You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UIKit:冷启动时从AppDelegate调用视图控制器中的函数

如何在ViewController中检测应用冷启动并在viewDidAppear前执行对应函数

原代码的核心问题是:application(_:didFinishLaunchingWithOptions:)执行时,目标ViewController还未完成初始化,appLaunchDelegate此时为nil,导致appDidLaunchFromColdStart()无法被调用。因为viewDidLoad要等到ViewController加载后才会执行,这时候已经错过了冷启动检测的时机。

下面提供两种可行的解决方案:

方案一:通过AppDelegate存储冷启动状态,在ViewController初始化阶段读取

这种方式实现简单,适合单一页面需要冷启动逻辑的场景:

  1. 在AppDelegate中添加静态属性存储冷启动状态
  2. 在冷启动触发时标记状态
  3. 在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执行")
    }
}

方案二:使用通知中心触发冷启动回调

这种方式扩展性强,适合多个页面需要监听冷启动事件的场景:

  1. 自定义冷启动通知名称
  2. 检测到冷启动时发送通知
  3. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 09:15:26