10

Update: Finally got it working. See below code for SceneDelegate.swift

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        window = UIWindow(frame: windowScene.coordinateSpace.bounds)
        window?.windowScene = windowScene
        window?.rootViewController = ViewController()
        window?.makeKeyAndVisible()
    }

In contrast to the tutorials and the articles online, I was not able to create a working UI with the latest Xcode. This was also the case with Xcode 10, but I did not care at the time.

My steps are as follows:

  1. Delete Main.storyboard
  2. Delete Main from project settings

Write basic UIWindow code:

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        window = UIWindow(frame: UIScreen.main.bounds)
        window?.makeKeyAndVisible()
        let mainVC = ViewController()
        window?.rootViewController = mainVC

        return true
    }

At this point I am getting an error saying cannot find the storyboard named Main in the bundle. If I go ahead and clear the entry from Info.plist, this time it complains that there are not enough characters in the storyboard name.

Any ideas?

fankibiber
  • 729
  • 1
  • 6
  • 19
  • I cannot reproduce your error. Can you please post the contents of your `Info.plist` file? Once I removed the storyboard line from `Info.plist` I was able to run the application properly. – Michael Fourre Sep 16 '19 at 22:34
  • https://imgur.com/a/H4Yzt5x - This is my info.plist before editing. I can now also launch the application with the black background, but I cannot modify it in any way. Cannot change any attributes of it. – fankibiber Sep 17 '19 at 06:40
  • Notice the Storyboard Name entry just below the selected line in your info.plist. You need to delete that. Then you need to move all your code into `scene(_:willConnectTo:)` as I explain here: https://stackoverflow.com/a/58251446/341994 – matt Oct 06 '19 at 23:36
  • To get UIScene frame size do `windowScene.coordinateSpace.bounds`. – Pedro Paulo Amorim Jan 15 '20 at 15:56

2 Answers2

16

These are the steps I followed to get UI working programmatically in Xcode 11.

1) Created a new project as usual

2) I deleted the Main.Storyboard file from the project navigator on the left-hand side.

3) In General tab I removed the Main option from the Main Interface drop-down list enter image description here 4) Next, go to your Info.plist file and completely remove the Storyboard Name from the list

enter image description here

5) Now if you run the app, it should not crash and it should show you a black screen.

6) Next, go to the SceneDelegate.swift file and initialise your UIWindow object as usual. There is a catch here and is new in Xcode 11. You also set the windowScene property of the window object, or else it won't work. enter image description here

7) Once that's all done, Go to your ViewController class and set the background colour of the view to some colour and you should be all good. enter image description here

You can also use templates: Xcode 11 Programmatic UIKit templates

Hope this helped you!!!

srm
  • 3,062
  • 16
  • 30
AKIL KUMAR
  • 287
  • 3
  • 8
  • For prevent layout issue, don't remove -Launch screen interface file base- key from Info.plist however, feel free to remove its values and LouchStoryboard file. – asilturk May 12 '21 at 14:45
1

This works for me on Xcode 10.3 Swift 5, and Xcode 11 Swift 5.1.

On your new Xcode project, on the Info.plist file, delete the launch screen and main interface file name entries, (don't leave the entry there with an empty string)

Remove the @UIApplicationMain attribute from your AppDelegate class.

Also, this link may help you, you can find info on UIApplicationMain https://docs.swift.org/swift-book/ReferenceManual/Attributes.html

See code below:

//  Created by Juan Miguel Pallares Numa on 9/16/19.
//  Copyright © 2019 Juan Miguel Pallares Numa. All rights reserved.

import UIKit

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var myViewController = ViewController()

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        window = UIWindow(frame: UIScreen.main.bounds)
        window?.rootViewController = myViewController
        window?.makeKeyAndVisible()

        return true
    }
}

import UIKit

class ViewController: UIViewController {

    convenience init() {
        self.init(nibName: nil, bundle: .main)
        view = UIView(frame: UIScreen.main.bounds)
        view.backgroundColor = UIColor(
            displayP3Red: 0.0, green: 0.7, blue: 0.0, alpha: 1.0)
    }
}

// call this file "main.swift"
import Foundation
import UIKit

UIApplicationMain(
    CommandLine.argc, CommandLine.unsafeArgv, nil, NSStringFromClass(AppDelegate.self))
Juanmi
  • 71
  • 1
  • 1
  • 7
  • I modified AppDelegate and ViewController as above and created the `main.swift` file. Deleted in total three entries from `info.plist`, one with LaunchScreen, and two other with the Main entry for the storyboard. I still get a black screen. Probably the issue resides from the newly added SceneDelegate.swift file. – fankibiber Sep 17 '19 at 06:31
  • I get a green background in the safe area, did you set the background color? also, just in case you want to browse documentation regarding the safe area, https://developer.apple.com/documentation/uikit/uiview/positioning_content_relative_to_the_safe_area – Juanmi Sep 17 '19 at 15:42
  • Yep. I tried with the init above, in viewDidLoad and loadView, but nothing. Is it possible to get the project in a .zip for me to try? – fankibiber Sep 17 '19 at 20:33
  • I downloaded Xcode 11 yesterday, I created a new single view iOS project that uses Swift UI and I get a white screen with the text "Hello World" in it, I did not need to add any code to get there. My posted answer has been tested with a Info.plist created by Xcode 10, unfortunately I don't have a way to share the zip, StackOverflow does not have an option for it. Also, it seems like Xcode 11 plist file is different, it has a scene delegate entry that is new to this IDE version. – Juanmi Sep 24 '19 at 17:27