0

I've been SLOWLY learning how to build iOS applications with Swift and was sent this article by someone why has been doing it professionally: A Case For Using Storyboards on iOS. Although I have taken the approach of learning how to build iOS application programmatically, I do believe that storyboards have their place in iOS development. I'm trying to implement Marin Benčević idea by having a new storyboard for every view w/ its own ViewController. However, I'm having issues getting this connected. I continuously run into this same error:

Failed to instantiate the default view controller for UIMainStoryboardFile 'LoginViewController' - perhaps the designated entry point is not set?

Now my file structure is a little different as I want to keep my views separated from my controllers but its as shown:

file structure

LoginViewController.swift:

class LoginViewController: UIViewController {
    override func viewDidLoad() {
        self.view.backgroundColor = UIColor.green
        let vc = LoginViewController.instance()
        self.present(vc, animated: true, completion: nil)
    }

    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }
}

AppDelegate.swift:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
    self.window = UIWindow(frame: UIScreen.main.bounds)
    let loginStoryboard = LoginViewController()

    self.window?.rootViewController = loginStoryboard
    self.window?.makeKeyAndVisible()

    return true
}

UIStoryboardExt.swift:

import UIKit

extension UIStoryboard {
    func initialViewController<T: UIViewController>() -> T {
        return self.instantiateInitialViewController() as! T
    }
}

UIViewControllerExt.swift:

import UIKit

extension UIViewController {
    class func instance() -> Self {
        let storyboardName = String(describing: self)
        let storyboard = UIStoryboard(name: storyboardName, bundle: nil)
        return storyboard.initialViewController()
    }
}

info.plist:

Main storyboard file base name: LoginViewController

All in all, I'm wondering how can I connect a UIViewController to a View.storyboard programmatically without having to use the property tab of the storyboard. I've tried so many different variations of how to do this but I cannot seem to figure it out.

Here was a StackOverflow Question that I also attempted to get working but could not:StackOverflow

EDIT

Along with what Christian Abella said, I did need to also set the class like of the storyboard objectClass

Nappstir
  • 995
  • 2
  • 20
  • 38
  • [Did you set the designated entry point?](https://stackoverflow.com/a/45211444/1361672) – RLoniello Jun 25 '18 at 22:33
  • 2
    Is there a reason you don’t want to use the properties tab? Its there for, well, a reason. If you are still learning, don’t overcomplicate things for yourself. If you want to get `initialViewController` from a storyboard, one must be marked as such, otherwise the system wouldn’t now what to do. Also, if you did get this to work, presenting `LoginViewController` inside of `LoginViewController.viewDidLoad()` would get you an endless loop of showing the same VC. – Losiowaty Jun 25 '18 at 22:34

1 Answers1

2

This is doable and I do this in some of my projects. But you need to do the following:

  1. Remove all "As Initial View Controller" ticks form your storyboard files.
  2. In the Apps' Settings go to General tab and clear the Main Interface from the Deployment Info
  3. In the Apps's Setting go to Info tab and clear the 'Main storyboard file base name' property.

      self.window = UIWindow(frame: UIScreen.main.bounds)
    
      let main : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    
      let loginVC = main.instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
    
      self.window?.rootViewController = loginVC
      self.window?.makeKeyAndVisible()
    
      return true
    

And as @Losiowaty pointed out, your viewDidLoad will cause an endless loop so you need to remove that code the present the LoginViewController.

Christian Abella
  • 5,747
  • 2
  • 30
  • 42
  • But then you still cannot get a VC by calling `UISToryboard.instantiateInitialViewController()`, can you? You should rather use `UIStoryboard.instantiateViewController(withIdentifier:)`, right? – Losiowaty Jun 26 '18 at 01:26
  • 1
    yep. identifier is needed. please see the sample code that I have added. – Christian Abella Jun 26 '18 at 01:32