Opt out of UISceneDelegate/SwiftUI on iOS

SwiftXcodeSwiftuiIos13

Swift Problem Overview


I'm currently using Xcode 11 Beta 5. Within my application, it runs fine on iOS 12 and under. However, on iOS 13 it looks like it's using the UIScene by default. This is causing my app to not do anything.

When the app launches on fresh install, there is a terms and conditions the user must accept. After agreeing they go to a loading screen which then directs them to the main view. In the screenshot I posted, the view behind the current one in foreground is the splash loading screen.

We will look into adding multiple views scene support throughout the application soon, but right now we have higher priority stuff we need to work on.

"Support multiple windows" is already disabled in the General settings of the app's target. Also I have Enable Multiple Windows set to NO in the info.plist file.

So far nothing has really worked. Basically I want to opt out/disable multiple windows and UIScene/SwiftUI to restore the original behaviour in iOS 10-12. Is this possible in iOS 13 or we have to update it?

Update:

Here is a screenshot of the view debug hierarchy. Left side is iOS 12, right side is on iOS 13. Without adding anything to the Info.plist nor any scene delegate classes or methods, why is it different? Pretty much just ran it in its existing production ready code on Xcode 11.

Swift Solutions


Solution 1 - Swift

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.

Solution 2 - Swift

This is something I faced also, and there's a few scenarios at play here:

  • If you want to work on an existing UIKit app in Xcode 11, simply open it up and it should work fine. All my apps have, with no SceneDelegate file nor any changes to AppDelegate or storyboards.
  • If you want to create a new UIKIT app targeting iOS 13, simply create it while making sure you leave the "Use SwiftUI" checkbox unchecked.

But I'm wondering if you are facing the third scenario - one that I did about a week ago. Creating a new `UIKit app targeting something earlier than iOS 13. (I actually targeted iOS 9!)

Yep, your template will give you 15 errors (as of beta 5), along with a SceneDelegate file/class. Fortunately, Xcode will help you auto-correct all but one.

The last one is to add one line that is part of the SceneDelegate class but unfortunately Apple left it out of the AppDelegate class - which after more than a dozen @available(iOS 13.0, *) clauses means you've opted out of SceneDelegate if running iOS 12 and guess what? It's not there in ApDelegate!

Add this to your AppDelegate:

var window: UIWindow?

At that point, your should have a running UIKit app targeted for iOS 12 and earlier.

Solution 3 - Swift

I got this to work using dfd's answer, but because my app is in Objective-C, I had to make one change:

In Objective-C, you want to put

@property (strong, nonatomic) UIWindow *window;

in AppDelegate.h (not in the .m)

Solution 4 - Swift

Okay so I figured it out. Due to the changes in iOS 13 of Apple's new default card presentation style, in my storyboard segue from my splash screen to my custom flow navigation controller defaulted to the new presentation (see screenshot below).

Segue

How I fixed that was to go back to the old style which defaulted to the old lifecycle. See screenshot below.

Storyboard seque kind

Not sure why it did, as this was the only place in my application that caused this (pretty big app so I have to spend some time going through all the storyboards to make sure).

Solution 5 - Swift

Xcode 12 - Swift 5.3 - iOS 14

Since Xcode 12 and with the help of Swift 5.3 and @main, you can have a multiplatform app that has no SceneDelegate or event AppDelegate. There will be only a simple file like:

import SwiftUI

@main
struct MyMultiPlatformApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

Solution 6 - Swift

While you're looking to opt out of it, sometimes the problem that prevents it from finding your sceneDelegate file lies in the info.plist file.

If you have this in the info.plist.

Scene Configuration
    Application Session Role
        Item 0 (Default Configuration)
            Delegate Class Name : SceneDelegate
            Storyboard Name : Main

It should be.

Scene Configuration
    Application Session Role
        Item 0 (Default Configuration)
            Delegate Class Name : $(PRODUCT_MODULE_NAME).SceneDelegate
            Storyboard Name : Main

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDavidAView Question on Stackoverflow
Solution 1 - SwiftrmaddyView Answer on Stackoverflow
Solution 2 - Swiftuser7014451View Answer on Stackoverflow
Solution 3 - SwiftNik BhattView Answer on Stackoverflow
Solution 4 - SwiftDavidAView Answer on Stackoverflow
Solution 5 - SwiftMojtaba HosseiniView Answer on Stackoverflow
Solution 6 - SwiftAlex ZavatoneView Answer on Stackoverflow