How to Migrate an Old Xcode Project to Use Swiftui

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:

Sample Image

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.

Sample Image

Sample Image


Addendum II:

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

Replacing UIKit with SwiftUI in an existing project

Don't worry about "removing traces." Fun fact: Importing SwiftUI at the top of a file ALSO imports UIKit.

What you said about the SceneDelegate and a UIHostingController is all you need actually. The only view controller you should ever need to load is the hosting controller. You literally just have a root view (ContentView or whatever) and start your whole app from that initial view. Be creative about your structure. Now is the time to experiment.

Include SwiftUI views in existing UIKit application

edit 05/06/19: Added information about UIHostingController as suggested by @Departamento B in his answer. Credits go to him!



Using SwiftUI within UIKit

One can use SwiftUI components in existing UIKit environments by wrapping a SwiftUI View into a UIHostingController like this:

let swiftUIView = SomeSwiftUIView() // swiftUIView is View
let viewCtrl = UIHostingController(rootView: swiftUIView)

It's also possible to override UIHostingController and customize it to one's needs, e. g. by setting the preferredStatusBarStyle manually if it doesn't work via SwiftUI as expected.

UIHostingController is documented here.



Using UIKit within SwiftUI

If an existing UIKit view should be used in a SwiftUI environment, the UIViewRepresentable protocol is there to help! It is documented here and can be seen in action in this official Apple tutorial.


Compatibility

Please note that you cannot use SwiftUI on iOS versions < iOS 13, as SwiftUI is only available on iOS 13 and above. See this post for more information.

If you want to use SwiftUI in a project with a target below iOS 13, you need to tag your SwiftUI structs with @available(iOS 13.0.0, *) attribute.

How do you migrate to the new SwiftUI App Protocol?

You need to follow these steps to migrate a SwiftUI application to the new App life cycle:

  1. Create a new App struct and add the @main annotation:
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}

  1. Remove the @main annotation from AppDelegate.

  2. Remove Scene Configuration from Info.plist:

Sample Image


  1. (Optionally) Move AppDelegate/SceneDelegate methods:
  • SwiftUI app life cycle iOS14 where to put AppDelegate code?
  • Is there any way to call SceneDelegate methods in iOS 14 app life cycle?

  1. Now you can remove the AppDelegate and SceneDelegate classes from the project (first make sure the app is indeed working as expected).

  2. Reinstall the app (as suggested in the comments).

Is there any way to use storyboard and SwiftUI in same iOS Xcode project?

I just started to look at the SwiftUI. Sharing a small example.

  1. In the storyboard add Hosting View Controller
  2. Subclass the UIHostingController with your own class (ChildHostingController)
    Sample Image
  3. ChildHostingController should look something like that:

import UIKit
import SwiftUI

struct SecondView: View {
var body: some View {
VStack {
Text("Second View").font(.system(size: 36))
Text("Loaded by SecondView").font(.system(size: 14))
}
}
}

class ChildHostingController: UIHostingController<SecondView> {

required init?(coder: NSCoder) {
super.init(coder: coder,rootView: SecondView());
}

override func viewDidLoad() {
super.viewDidLoad()
}
}

For more details have a look at Custom UIHostingController

Apple Docs UIhostingController (Unfortunatelly it hasn't been documented yet)

Integrating SwiftUI Video

Move existing SwiftUI app to the new Xcode 12 SwiftUI App Live Cycle

Nope, but I did it and it is very very easy. It is just to move your AppDelegate methods to the new App struct and make some changes in dataflow.

I experienced some performance boost after change the model, but I don't know if it is real or macOS Big Sur issues.

Opt out of UISceneDelegate/SwiftUI on iOS

While you should embrace using scenes when your app is run under iOS 13 and later, you can fully opt out while you still support iOS 12 or earlier.

  • Completely remove the “Application Scene Manifest” entry from Info.plist.

  • If there is a scene delegate class, remove it.

  • If there are any scene related methods in your app delegate, remove those methods.

  • If missing, add the property var window: UIWindow? to your app delegate.

Your app should now only use the app delegate and under iOS 13 it should have the same life cycle as iOS 12.

Note: None of this is specific to Swift or SwiftUI.



Related Topics



Leave a reply



Submit