Group Group Group Group Group Group Group Group Group

Chapter 3 - Dog Walk App (Fails when embedded in Tab Bar Controller)

#1

I completed Chapter 3, the Dog Walk app. It works fine and I’ve created another app based on this that also works fine BUT, when I tried embedding it in a tab bar controller it failed. As a test, I downloaded the completed Dog Walk app that complements the book and I get the same identical error when I embed that in a Tab Bar Controller. Can anyone explain what I need to do to fix the problem as I’ve tried various options and help sources but I don’t yet have the experience to solve this myself.

The Dog Walk app fatal errors shows on line 62 of View Controller.swift, the line is:
let results = try managedContext.fetch(dogFetch)
Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value)

I thought it is actually related to the code in AppDelegate as the root View Controller has changed - but I can’t actually solve it! Any help would be much appreciated!

[Post submit: I’ve just noticed my username shows as christ… my first name is Chris, last name starts with T!!!]

#2

It seems very likely that the nil object causing the error is the managedContext. That gets set by code in AppDelegate, and that code doesn’t expect a Tab Bar Controller.

Existing code in AppDelegate:

  func application(_ application: UIApplication, didFinishLaunchingWithOptions
    launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    if
      let navController = window?.rootViewController as? UINavigationController,
      let viewController = navController.topViewController as? ViewController
    {
      viewController.managedContext = coreDataStack.managedContext
    }
    return true
  }

Your root controller is no longer a UINavigationController, so the navController is nil, and the viewController.managedContext is never assigned.

What you need is to replace that “if block” with something like this, which starts by getting the tab controller, then gets the navigation controller from it’s first tab (viewControllers?[0]), then gets the view controller from that and does the assignment.

    if
      let tabController = window?.rootViewController as? UITabBarController,
      let navController = tabController.viewControllers?[0] as? UINavigationController,
      let viewController = navController.topViewController as? ViewController
    {
      viewController.managedContext = coreDataStack.managedContext
    }
#3

Oh wow, you are brilliant, thank you so much for your help! In my own efforts I had come to a similar conclusion but I couldn’t piece it altogether as you have, I’m pleased I got close but a massive thank you for taking the time to look at this, you are a star! I’m so happy!