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

3

25

I have an app made in Xcode 10 using Main.storyboard and would like to migrate it to use Apple's new framework: SwiftUI.
Is that already possible?

I have already tried to add the UIApplicationSceneManifest key in Info.plist, I changed the AppDelegate.swift to use scenes, I created the SceneDelegate.swift and even then I could not

Alphonsoalphonsus answered 9/6, 2019 at 14:36 Comment(5)
What kind of error are you getting?Malachy
After launching the LaunchScreen.storyboard, the screen becomes blackAlphonsoalphonsus
There are requirements...(1) Xcode 11 beta 1, (2) device needs to be iOS13 beta 1, (3) if you wish to use Xcode 11 Previews, run it on macOS 10.15 Catalina. And even there, there is no migrator. Also, SwiftUI replaces Storyboards and doesn't use AutoLayout. recommend taking it very slow - start with a new project. If you must use an existing app, keep in mind that any SwiftUI pieces will require iOS13 come Fall 2019.Spring
Thanks. All requirements are met. And I intend to use testflight at the moment for people who are using the beta and prepare my app for when iOS13 is releasedAlphonsoalphonsus
I get a black screen too but in my case it doesn't depend on using SwiftUI. I created an empty project with storyboard in Xcode 11 and decided to delete this storyboard and add view controllers manually. The mistake was I added this code in "app delegate" but should do the similar thing in "scene delegate".Salve
M
32

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.

Malachy answered 9/6, 2019 at 15:3 Comment(6)
@AiltonVieiraPintoFilho please check Addendum I at the bottom of the answer for additional instructions - I just tried all of them on a project createad with Xcode 10.2.1 and I got it workingMalachy
I returned the commit, tried again and it worked. Thank you!Alphonsoalphonsus
Faced with the same problem. I had to completely clean derived data and remove app from simulator to make changes working.Clap
I've been messing with this for hours. I've checked every setting as per above and nothing works. I've breakpointed in the app delegate and noticed that the scene session being passed in has a role of external display. I've tried all sorts of things and cannot get it to load correctly. If I manually create a scene config on the debug console with an application role, it loads perfectly. So the problem seems to be that the app is somehow deciding it is an external display and I can't find anything that changes that.Array
How to change the rootview controller for mac app. I am converting my old iPhone for mac, and in that after user login once in app. If user open app again i need to change the storyboard. i am facing issue in that.Enplane
Build Settings -> Enable Previews NOT Build Options -> Enable PreviewsMcchesney
S
8

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

Saltigrade answered 30/9, 2019 at 19:48 Comment(0)
A
4

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.

Array answered 19/6, 2019 at 12:14 Comment(3)
as on device, remove app and reinstallWillem
Wow, I searched high and low in my project which I was migrating, doubting myself. This did it!Vambrace
for me, its setting the delegate correctly but I am not getting the sceneClass set as (null)Poliomyelitis

© 2022 - 2024 — McMap. All rights reserved.