Is it possible to migrate an old Xcode project to use SwiftUI?

I assume you're using Xcode 11 GM and macOS Mojave or Catalina.

Along with the changes in the plist, you have to add UISceneSession lifecycle functions in the application delegate.

func application(_ application: UIApplication,
                 configurationForConnecting connectingSceneSession: UISceneSession,
                 options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    // The name must match the one in the Info.plist
    return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}

func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {

}

Also, you need to make sure the window is created correctly in the SceneDelegate.

func scene(_ scene: UIScene, 
           willConnectTo session: UISceneSession, 
           options connectionOptions: UIScene.ConnectionOptions) {

    guard let windowScene = scene as? UIWindowScene else {
        return
    }

    let window = UIWindow(windowScene: windowScene)
    window.rootViewController = UIHostingController(rootView: ContentView())
    self.window = window
    window.makeKeyAndVisible()
}

where ContentView is the main SwiftUI view you want to display.

P.S. Make sure the plist specifies $(PRODUCT_MODULE_NAME).SceneDelegate as delegate class name, and the scene delegate is called SceneDelegate

Example:

enter image description here

If you're on Catalina, you can turn on Previews in the build settings for your target.

Build Options -> Enable Previews


Addendum I:

Make sure you remove the Storyboard key from the Info.Plist and that you're targeting iOS 13.

enter image description here

enter image description here


Addendum II:

Clean Derived Data, as many devs in the comments suggest.


My solution turned out to be different. In my case, I had everything in place, but when the code attempted to load the UISceneConfiguration, it failed to load the config in the Info.plist and gave me a secondary window config instead with no scene delegate set. If I asked for the correct configuration from the debug console it would load as expected. I was confused.

I double checked everything and tried all of the suggestions here but none worked. In the end I did 'Hardware' - 'Erase all contents and settings...' on the simulator and that solved it.

My guess is that because I'd been running the pre-SwiftUI version of the app on the simulator, something in that caused the SwiftUI version to behave differently.


It's a correct only minor change

In SceneDelegate.swift replace

let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = UIHostingController(rootView: ContentView())
self.window = window
window.makeKeyAndVisible()

with

if let windowScene = scene as? UIWindowScene {
    let window = UIWindow(windowScene: windowScene)
    window.rootViewController = UIHostingController(rootView: ContentView())
    self.window = window
    window.makeKeyAndVisible()
}

TAKEN FROM HERE