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

SwiftUI应用每次打开(非仅首次启动)时运行代码的相关问题

问题解答

A. 问题出现的原因

  • 你将需要每次打开应用执行的逻辑放在了AppContentView的init方法中,该方法仅会在视图首次实例化(即应用冷启动)时执行一次,后续应用从后台恢复到前台时,视图不会重新实例化,对应逻辑自然不会触发。
  • 你已经在主App结构中声明了scenePhase环境变量,但没有添加对该变量变化的监听逻辑,等于没有用到系统提供的场景状态变化回调能力。
  • 你怀疑的AppContentView中的switch路由语句和当前问题无关,它仅负责视图切换,不会影响逻辑的执行时机。

B. 修复方案

核心思路是通过监听scenePhase的状态变化,在应用进入前台激活状态时执行对应逻辑,修改后的代码如下:

@main
struct CouponDeckApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    @Environment(\.scenePhase) private var scenePhase
    var body: some Scene {
        WindowGroup {
            AppContentView()
                .onChange(of: scenePhase) { newPhase in
                    // 应用进入前台激活状态时触发
                    if newPhase == .active {
                        let userDefaults = UserDefaults.standard
                        
                        // 仅首次启动需要执行的默认值设置逻辑可以保留在原来的init中,需要每次执行就挪到此处
                        if userDefaults.value(forKey: "hour") == nil {
                            userDefaults.set(9, forKey: "hour")
                        }
                        if userDefaults.value(forKey: "minute") == nil {
                            userDefaults.set(30, forKey: "minute")
                        }
                        
                        // 其他每次打开应用需要执行的逻辑都可以写在这里
                    }
                }
        }
    }
}

struct AppContentView: View {
    @State var currentview: String = "Main"
    
    // 如果默认值设置仅需首次执行,可以保留在init中,否则直接删除移到上面的active回调里
    init() {
        let userDefaults = UserDefaults.standard
        
        if userDefaults.value(forKey: "hour") == nil {
            userDefaults.set(9, forKey: "hour")
        }
        if userDefaults.value(forKey: "minute") == nil {
            userDefaults.set(30, forKey: "minute")
        }
    }
    
    var body: some View {
        Group {
            switch currentview {
            case "Main":
                MainView(currentview: $currentview)
            case "Form":
                FormView(currentview: $currentview)
            case "Settings":
                SettingsView(currentview: $currentview)
            default:
                if currentview.contains("Coupon") {
                    CouponView(currentview: $currentview)
                }
                else {
                    EditView(currentview: $currentview)
                }
            }
        }
    }
}

C. 其他替代方案

  • 基于AppDelegate实现:在AppDelegate中实现applicationDidBecomeActive:方法,该方法会在应用每次进入前台激活状态时被调用,直接把要执行的逻辑写在这个方法中即可。
  • 基于系统通知实现:监听UIApplication.didBecomeActiveNotification系统通知,在需要执行逻辑的模块中注册该通知的观察者,收到通知时触发对应代码。
  • 基于特定视图生命周期实现:如果逻辑仅需要在某个指定页面显示时执行,可以把逻辑写在对应页面的onAppear修饰器回调中,若需要过滤非应用激活的触发场景(比如页面push/pop返回的场景),可以和scenePhase状态判断结合使用。

内容的提问来源于stack exchange,提问作者Kunal Katiyar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 20:06:01