Chapter 9, different initial view controller?

Hello.
I’m trying to use code from Chapter 9 in “Core Data by Tutorials 3.1”, but I don’t want my initial View Controller being the JournalListViewController. Instead, i want to have another view controller, in which I will be placing a button, that when tapped, will take me to the list-view.

If I try to set another initial view controller, I get the fatalError: “Application Storyboard mis-configured”. I see the error has to be in the AppDelegate.swift, but what should I do about that piece of code? This is the code I have in the AppDelegate:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?
lazy var coreDataStack = CoreDataStack(modelName: "Neptune")

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    _ = coreDataStack.mainContext
    
    guard let navigationController = window?.rootViewController as? UINavigationController,
        let listViewController = navigationController.topViewController as? JournalListViewController else {
            fatalError("Application Storyboard mis-configuration")
    }
    
    listViewController.coreDataStack = coreDataStack
    
    return true
}

func applicationWillTerminate(_ application: UIApplication) {
    coreDataStack.saveContext()
}
}

Your AppDelegate is using a guard to ensure that the initial view controller in your app (as presently defined in your storyboard) is a UINavigationController, and its first view controller is a JournalListViewController. If this is not true your app will crash.

If you’ve changed your storyboard, you should change the conditions in this guard to match. What you change it to depends on how your app is structured though, so it’s difficult to give you specifics.

Yes, I understand that, but what is the code there for?

About the structure of my ‘Storyboard’, I only added another ViewController, set that new ‘ViewController’ as my ‘Initial View Controller’, added a button that when clicked takes me to the ‘Master Scene’. I also created a ‘UIViewController’ class for that new ViewController. See the attached picture if you are unsure what I mean.

Please reply if there is anything you’d like me to specify :))

Why that code is there: I’m going to speculate that it’s there as a simple error-check for the developer. In the example, the listViewController needs a core data stack, but the AppDelegate’s reference to the view controller isn’t definite; it relies on the storyboard being configured correctly, and that returns an optional. You could write a line of code which would force-unwrap any optionals along the way, but if the storyboard isn’t configured correctly then all you’ll get in your Xcode console is something like ‘Force-unwrapped optional unexpectedly had a value of nil’. This way you get a descriptive error message.

In your example, your initial view controller (which will become the value of window?.rootViewController) appears to be a subclass of UIViewController. It doesn’t appear to have a container view controller (e.g. a navigation controller or tab bar controller) for a parent. So in the app delegate you could do something like guard let viewController = window?.rootViewController as ViewController.
The second view controller in your diagram, which looks like it has a ‘show’ segue to it but no navigation controller to push the new view controller onto, would have to be passed references to your core data stack via segue, I think. If there’s a different relationship between the view controllers then that’s not evident to me.

Hmm, does this picture provide the needed information about the navigation controller?

Otherwise, just tell me what information you need…

It doesn’t help me much yet; it’s not a conventional flow.

Normally, you have a single navigation controller, with an initial ‘top’ view controller embedded in it. You then ‘show’ (or push, it’s a stack) a new view controller onto the navigation controller’s stack. So your storyboard’s initial view controller would be the navigation controller, and each subsequent view controller would have a single show segue to the next.

Your storyboard has an initial view controller which isn’t a navigation controller. It ‘shows’ a navigation controller (segueing to one is fine, but I don’t see a way back to your initial view controller unless you programmatically dismiss the navigation controller. The first navigation controller’s embedded view controller segues to a second navigation controllers, so you can’t get back to the first. (Ignoring the Core Data part of this app - does just using the app work how you expect it to? Does the back button appear to let you dismiss screens?)

I’m not sure what your user experience is supposed to be from this diagram. And apart from the navigation controllers, I can’t tell if any view controller has a reference to any of the ones after it without seeing their code, so I don’t see a way for the app delegate to refer to any view controller other than the initial view controller.