swiftuiappdelegate

SwiftUI AppDelegate not being ran whenever app is opened


Here is a simple AppDelegate that I have made:

import SwiftUI

class AppDelegate: UIResponder, UIApplicationDelegate {

    private func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
        print("application")
        // first launch
        // this method is called only on first launch when app was closed / killed
        return true
    }

    private func applicationWillEnterForeground(application: UIApplication) -> Bool{
        print("applicationWillEnterForeground")
        // app will enter in foreground
        // this method is called on first launch when app was closed / killed and every time app is reopened or change status from background to foreground (ex. mobile call)
        return true
    }

    private func applicationDidBecomeActive(application: UIApplication) -> Bool {
        print("applicationDidBecomeActive")
        // app becomes active
        // this method is called on first launch when app was closed / killed and every time app is reopened or change status from background to foreground (ex. mobile call)
        return true
    }
}

@main
struct CouponDeckApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    @Environment(\.scenePhase) private var scenePhase
    var body: some Scene {
        WindowGroup {
            AppContentView()
                
        }
    }
}

The AppDelegate doesn't seem to be calling any of its functions, though. It should be running them at 3 places, but none are running. Why is this happening, and how do I fix it?


Solution

  • You've marked your app with @main which makes it app entry point.

    Not all methods of app delegate will work with UIApplicationDelegateAdaptor, like here applicationWillEnterForeground applicationDidBecomeActive won't be called.

    Instead you're supposed to use publishers inside SwiftUI view, like this:

    .onReceive(NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)) { _ in
        print("applicationDidBecomeActive")
    }
    .onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
        print("applicationWillEnterForeground")
    }
    

    An other problem with your AppDelegate is that it doesn't have needed methods signature. When you're adding new method, don't paste it from somewhere, instead type a couple of letters from method name and let Xcode finish the rest. In your case if you have your signature correct, private would be an error reported by Xcode.

    If you still wanna get them inside your delegate for some reason, you need to move @main to AppDelegate, and initialize your SwiftUI view with UIHostingController like it was back done in SwiftUI 1:

    @main
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        var window: UIWindow?
        
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
            let window = UIWindow()
            self.window = window
            window.rootViewController = UIHostingController(rootView: ContentView())
            window.makeKeyAndVisible()
            return true
        }
        
        func applicationWillEnterForeground(_ application: UIApplication) {
            print("applicationWillEnterForeground")
        }
        
        func applicationDidBecomeActive(_ application: UIApplication) {
            print("applicationDidBecomeActive")
        }
    }
    

    Also you need to update Info.plist, set enable multiple windows to NO: