Create Apps Without A Storyboard In Swift

Pretty much all of my career has been spent programming for the web. I build websites with HTML, CSS, Javascript, and various backend technologies. At times I’ve worked with other tools and stacks that weren’t directly related to the web, but no matter what, I always tend to gravitate back to web development. There’s something about writing software that outputs a document, and then allowing anyone in the world to access that document that intrigues me. Over time the software I wrote generated more complex docucuments and more dynamic documents. The one thing that didn’t change though was the fact that I built the views programmatically. I built the views using code, not some GUI or interface builder.

I never really had an itch to pick up mobile programming, but once Apple released the Swift programming language I was intrigued. I’ve tried multiple times throughout my career to learn iOS programming but I always noticed the one thing that always held me back was that every time I tried to learn Swift I ended up struggling because the views were built with XCode’s Interface Builder. I would buy books because that’s how I learn best. But every book I picked up started with the Interface Builder. My problem was I had to learn more about how the Interface Builder worked, than how iOS or Swift worked. I would easily forget what icons meant or what where certain attributes lived in the Interface Builder.

I finally realized that I could skip the Interface Builder completely and built my views 100% programmatically. This is easier for me to comprehend because I don’t need to memorize how to navigate a new IDE that I’m not familiar with.

I’m documenting here how to build an iOS app without a storyboard so that I can reference it later.

  1. Delete the storyboard in Project Navigator. This doesn’t actually tell our app to not use the storyboard. If we start the app it will still look for the storyboard and crash. What we have to do is tell our app to start the app from another location

  2. Click on the project’s name in the Project Navigator. In the target’s options click General > Deployment Info. Look for a field named Main Interface. There should be a value of Main in the dropdown. Clear out this field to prevent the app from crashing on startup.

  3. If we launch our app at this point we will see a blank screen, because our app doesn’t know which view to load on startup anymore. What we need is to tell our app which window to load, and what to display in that window. Open up the AppDelegate so that we can create our first window and UIViewController. In the didFinishLaunchingWithOptions function create a new window:

     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
         window = UIWindow(frame: UIScreen.main.bounds)   
         return true
     }
    

    Even though we have a window now, we still need a view controller to handle the logic. Create a UIViewController. We’ll set the background to blue to we know we’re loading it.

     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
         window = UIWindow(frame: UIScreen.main.bounds)
            
         let mainViewController = UIViewController()
         mainViewController.view.backgroundColor = UIColor.blue
            
         return true
     }
    
  4. The next step is to tell our app that this is the first view controller to load, which is known as the root view controller, which is a property of the window:

     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
         window = UIWindow(frame: UIScreen.main.bounds)
            
         let mainViewController = UIViewController()
         mainViewController.view.backgroundColor = UIColor.blue
            
         window!.rootViewController = mainViewController
            
         return true
     }
    
  5. And finally, the last step is to show the window on the screen:

     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
         window = UIWindow(frame: UIScreen.main.bounds)
             
         let mainViewController = UIViewController()
         mainViewController.view.backgroundColor = UIColor.blue
             
         window!.rootViewController = mainViewController
         window!.makeKeyAndVisible()
             
         return true
     }
    

Now if you launch the app you should see a screen with a blue window. Now you can continue to build out your views and navigation heirarchy without worrying about learning the Interface Builder.