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:
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
.
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:
- Create a new
App
struct and add the@main
annotation:
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
Remove the
@main
annotation fromAppDelegate
.Remove
Scene Configuration
fromInfo.plist
:
- (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?
Now you can remove the
AppDelegate
andSceneDelegate
classes from the project (first make sure the app is indeed working as expected).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.
- In the
storyboard
addHosting View Controller
- Subclass the
UIHostingController
with your own class (ChildHostingController
) 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
Swift - Pushviewcontroller from Appdelegate, Rootviewcontroller.Navigationcontroller Is Nil
Using Generic In-App Purchase Items for a Dynamic Range of Digital Products
Attribute Unavailable Warning on iOS Versions Prior to 8.0
Uitableviewcell Height Resize When Image Is Downloaded
What's Currently the "Correct" Way to Set a Uiview's Corner Radius
Afnetworking - Do Not Cache Response
Xcode 6.3.2 Can't Run on Osx 10.11 El Capitan Developer Preview 3
How Big Can the Payload Be When Sending Data via Watchconnectivity
Detect and Use Optional External C Library at Runtime in Objective-C
Google Objective-C API 'Gtl' with Swift
Schedule Number of Local Notifications
Ios/Swift - Hide/Show Uitabbarcontroller When Scrolling Down/Up
Swift How to Modify Exif Info in Images Taken from Mobile Camera
Endless Scrolling Background in Spritekit
Custom View Which Looks Like Uialertview
iPhone Opengl Es 2.0 - Pixel Perfect Textures
iOS 11+ How to Migrate Existing Core Data to Shared App Group for Use in Extension