Azhagusundaram Tamil
Azhagusundaram Tamil

Reputation: 2391

How to get UIWindow value in iOS 14 @main file?

I can able to access didFinishLaunchingWithOptions by below implementation. But, I need UIWindow variable. I don't know how to get it. I'm using Xcode 12 beta. iOS14, SwiftUI lifecycle.


import SwiftUI

@main
struct SSOKit_DemoApp: App {
    
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

class AppDelegate: NSObject, UIApplicationDelegate {
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        
        print("hello world!!!")
        return true
    }
}

Upvotes: 9

Views: 7068

Answers (3)

Mojtaba Hosseini
Mojtaba Hosseini

Reputation: 119272

You can access the keyWindow through an @Environment variable from anywhere like:

@Environment(\.keyWindow) private var keyWindow

By simply extending the EnvironmentValues it like:

extension EnvironmentValues {
    var keyWindow: UIWindow? {
        get { self[KeyWindow.self] }
        set { self[KeyWindow.self] = newValue }
    }
}

struct KeyWindow: EnvironmentKey {
    static var defaultValue: UIWindow?
}

💡 Keep it updated

You need to add a simple logic to keep the keyWindow always up-to-date like:

@main
struct MyApp: App {
    @State private var keyWindow: UIWindow? // 👈 A simple storage

    var body: some Scene {
        WindowGroup {
            ContentView()
                .onAppear { keyWindow = UIApplication.shared.connectedScenes.lazy.compactMap { ($0 as? UIWindowScene)?.keyWindow }.last } // 👈 Get the default key window (This is required for the UIKit)
                .onReceive(NotificationCenter.default.publisher(for: UIWindow.didBecomeKeyNotification)) { keyWindow = $0.object as? UIWindow }  // 👈 Update the storage on change
                .environment(\.keyWindow, keyWindow) // 👈 Pass in the updated window
        }
    }
} 

Here is the AppKit version

Upvotes: 2

Boris
Boris

Reputation: 17

iOS 14.7

@main
struct TestApp: App {

    var window: UIWindow? {
        guard let scene = UIApplication.shared.connectedScenes.first,
              let windowScene = scene as? UIWindowScene else {
            return nil
        }
    
        return .init(windowScene: windowScene)
    }
}

Upvotes: 2

Matteo Pacini
Matteo Pacini

Reputation: 22846

From iOS 13 onwards, it's safe to assume that the correct way to obtain a reference to the key window is via UIWindowSceneDelegate.

@main
struct DemoApp: App {
    
    var window: UIWindow? {
        guard let scene = UIApplication.shared.connectedScenes.first,
              let windowSceneDelegate = scene.delegate as? UIWindowSceneDelegate,
              let window = windowSceneDelegate.window else {
            return nil
        }
        return window
    }

    [...]
}

Upvotes: 24

Related Questions