Search code examples
iosswiftuiuikitlifecycle

Migrating SwiftUI lifecycle to UIKit's


I have an app already in production that uses SwiftUI's lifecycle (paired with an AppDelegate). Due to some specific behaviour of the app, we decided to migrate the app to use UIKit's lifecycle, adding the corresponding SceneDelegate to the app, as well as modifying the Info.plist file accordingly to accommodate to these new changes.

Although everything seems to work when installing the app from zero, installing it on top of a previous version makes the screen go black so the user cannot interact with the app at all unless they reinstall it completely. As I've read online, iOS is reusing the window configuration from the previous execution of the app. I know this because the AppDelegate's application(application:connectingSceneSession:options) is not being called when coming from a previous version of the app.

I would like to know if anyone has experienced this behaviour and how did they do to solve it, because we cannot ask our user base to reinstall the application.

Edit:

After a lot of debugging and messing with the existing code, I've found a way to circumvent the problem. It seems like using the SwiftUI lifecycle and attaching the SceneDelegate does work. At least partially, because right now I am using an EmptyView as the root of my app in SwiftUI even though I then initialise the app in the SceneDelegate correctly. This allows me to partially use the UIKit lifecycle, but I cannot abandon SwiftUI's lifecycle completely. I like the solution if it can be used as a partial update for the app that should be followed by another update that really uses only UIKit's lifecycle.

When I check the UIApplication object in the AppDelegate, I see that it has an openSession already configured, and I've seen that it has a AppSceneDelegate associated (which is presumably created by SwiftUI). Now, my question is, is there a way to remove this opened session? It will be great as a final update for my app, because having a hybrid SwiftUI-UIKit's lifecycle is a solution I don't really love right now.

Edit 2: Even though the app works and Universal Links are correctly handled with the SceneDelegate when the app is firstly opened by a Universal Link, tapping a Universal Link when the app is in background doesn't trigger the corresponding method in the SceneDelegate but instead, it should be handled via onOpenURL in SwiftUI. Once again, I guess this is because the weird hybrid lifecycle that I had to use to make it work.


Solution

  • After messing around with it I've found the problem and how to fix it.

    The problem was that there's an option in the Build Settings of Xcode called Application Scene Manifest (Generation) by default when the project is created with SwiftUI (I don't know about UIKit) this option is set to YES. This configuration seems to override whatever values you set in your Info.plist regarding the Scene Configuration, thus leaving the app with a black screen with no content. The solution wat setting that configuration to NO and, magically, the screen appeared correctly on my device.