165

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.

epologee
  • 11,229
  • 11
  • 68
  • 104
DavidA
  • 1,809
  • 3
  • 13
  • 12
  • Do you need to support only iOS 13 and later or do you need to support iOS 13 and iOS 12? – rmaddy Aug 12 '19 at 19:28
  • @rmaddy support between iOS 11-13+ (future versions). – DavidA Aug 12 '19 at 19:29
  • Is your main UI via code or storyboard? – rmaddy Aug 12 '19 at 19:59
  • @rmaddy it's done in storyboards has a segue to it's referenced xib ViewControllers. – DavidA Aug 12 '19 at 20:03
  • Without specific details on what your app is doing and when, it's hard to tell. Note that view controller methods such as `viewWill|DidAppear` are not called the same in iOS 13 when dismissing presented view controllers, for example. Add lots of lifecycle debugging messages and breakpoints and compare the flow between iOS 12 and 13 and see where it's different. – rmaddy Aug 12 '19 at 20:18
  • @rmaddy thanks. I suspect that may be it. I'll spend time debugging to figure it out. – DavidA Aug 13 '19 at 13:24
  • I have been experiencing the same issue in my own project which has support back to iOS 9.0. I'm currently putting it down to "Beta issues"; although it's interesting that both Beta 5 and 6 are having this. I'll see what happens with 7. According to Apple docs not having 'UIApplicationSceneManifest' in Info.plist should mean the app doesn't use scenes at all. – Harry Aug 27 '19 at 09:32

6 Answers6

420

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.

Revanth Kausikan
  • 673
  • 1
  • 9
  • 21
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • We posted answers at the same time. :-) One question - that missing line in `AppDelegate` that I addressed. Does that automatically come back in this process you described? (I kind of like your answer better, as it completely disregards scenes.) –  Aug 12 '19 at 19:38
  • Thanks for the quick response. I did complete this, removed it from Info.plist, also there isn't any scene delegate classes (existing application I just ran on Xcode 11), nor any methods present. From my understanding it's currently using the AppDelegate but I can't seem to figure out why on iOS 13 it has a different lifecycle. I added an update to my initial post with a screenshot. – DavidA Aug 12 '19 at 19:46
  • 1
    Same is happening for me and I have no manifest entry in my Info.plist neither any AppDelegate methods and also no SceneDelegate class. I am setting my controller like "terms and conditions" for David as rootViewController and it is appearing the same as shown here in the question above. Please help as I am stuck with this UI glitch and cant move forward.. ugh! – Mohsin Khubaib Ahmed Sep 23 '19 at 12:30
  • 1
    @MohsinKhubaibAhmed You are asking about a completely different issue. See https://stackoverflow.com/questions/56435510/presenting-modal-in-ios-13-fullscreen – rmaddy Sep 23 '19 at 15:42
  • 3
    Hi there! I followed the 3-step-instruction but got a black screen after the launch screen appears. Main Storyboard is selected and also the initial view controller. Do you have any suggestions? – user3191334 Nov 27 '19 at 10:09
  • 1
    @user3191334 I got the black screen too. In my case it was dark mode giving me a default black background. Add some content to your base storyboard and all will appear. – Gordon Dove Feb 08 '20 at 09:23
  • It's also probably smart to add back the standard AppDelegate methods to the AppDelegate.m since they are no longer there when making a SceneDelegate based app --- they are: ```- (void)applicationWillResignActive:(UIApplication *)application {} - (void)applicationDidEnterBackground:(UIApplication *)application {} - (void)applicationWillEnterForeground:(UIApplication *)application {} - (void)applicationDidBecomeActive:(UIApplication *)application {} - (void)applicationWillTerminate:(UIApplication *)application {}``` – Albert Renshaw Feb 28 '20 at 07:12
  • 2
    Thank you for the answer. I was also getting a black screen when setting the `rootViewController` to my custom view controller, forgetting that I needed to actually instantiate the `window` property after adding it to the `AppDelegate`. Don't forget to do that! `window = UIWindow()`, if you don't already do that. – BJ Miller Apr 21 '20 at 15:33
  • 1
    Make sure `window` **isn’t declared as weak**, or you will get a black screen! – Nicolas Miari May 11 '20 at 05:24
  • ``` NSMainStoryboardFile Main ``` – Coder ACJHP May 13 '20 at 09:29
  • 2
    If you are creating the app on the Xcode 12 (beta) you'll also need to replace "@main" annotation with "@UIApplicationMain". – Borut Tomazin Aug 13 '20 at 08:11
  • I may add this: At ObjC the AppDelegate.h have to contain @property (strong, nonatomic) UIWindow *window; – Ahmed El-Bermawy Sep 06 '20 at 01:57
  • 1
    Sill needed to add `@UIApplicationMain` instead of `@main` – Siempay Nov 14 '20 at 12:27
48

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.

Nimantha
  • 6,405
  • 6
  • 28
  • 69
  • Thanks for this. My scenario is pretty much the first point you said, an existing UIKit app in Xcode 11. But when I open it up, it doesn't work fine. Look at the update I added of the view debug hierarchy. – DavidA Aug 12 '19 at 19:44
  • Also in the AppDelegate, it already has var window: UIWindow? – DavidA Aug 12 '19 at 19:52
  • You had me concerned! (And I'm still a bit worried.) I've updated very little for my existing apps - last week was frustration with SwiftUI and I was curious about trying a layout in UIKit for iOS 13 only. But my existing apps? They support iPad multi-tasking but *left unchanged* in Xcode 11 I have no `SceneDelegate` and testing around says (a) they work in iOS 13 and (b) they don't support multiple windows at all, just split view between two apps. (I also don't support drag-and-drop.) Is there something else going on on your end? –  Aug 12 '19 at 20:18
  • To repeat, I simply opened my Xcode 10 app in Xcode 11. No `SceneDelegate`, no `SwiftUI`, no ability to create multiple instances of my iOS 9+ apps. Performance is the same as always - all of them are `CoreImage` custom filters updating in real-time - and, well, for me? If there's some OS related cruft related to scenes in the view hierarchy, it's moot if if doesn't support scenes. (And to finish, yeah, I am still a bit concerned. But it's also beta 5.) Hopefully you have a good backup that can reproduce what I'm seeing. –  Aug 12 '19 at 20:23
  • Thanks. I suspect its something within the lifecycle. I'll spend time debugging my application. I'll update this whenever I figure it out to help out anyone in a similar situation – DavidA Aug 13 '19 at 13:25
14

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)

Nik Bhatt
  • 373
  • 3
  • 12
4

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).

DavidA
  • 1,809
  • 3
  • 13
  • 12
  • 2
    Your question asks how to opt out of using scenes. This answer does not provide a solution to opting out of scenes. This should not be the accepted answer. If all you wanted to do was to avoid the new card-style presentation, you could have found that answer in several duplicates addressing that question. – rmaddy Sep 23 '19 at 15:40
  • This is one technique, but really you need to handle the code in your AppDelegate. You can also set your sceneDelegate's `modalPresentationMode` to be `.fullScreen` and you'll never have to worry about changing this. – Alex Zavatone Jun 22 '21 at 21:47
4

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()
        }
    }
}
Mojtaba Hosseini
  • 95,414
  • 31
  • 268
  • 278
0

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
Alex Zavatone
  • 4,106
  • 36
  • 54