0
votes

I have been following a tutorial to create a to-do list. I have a Tab Bar View Controller already managing 2 sets of Table View Controllers (WeekAViewController - item #1 & WeekBViewController - item 2).

Now, when I connect my Tab Bar View Controller to AllListsViewController (to become my 3rd set or item - code is down below), I get the following message in the debug window pointing to my AppDelegate:

Could not cast value of type 'UITabBarController' (0x1ad56a0) to 'UINavigationController' (0x1ad5678). (lldb)

How could I resolve this issue, please? (App Delegate code below)

Thanks

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    let dataModel = DataModel()


    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

        let navigationController = window!.rootViewController as! UINavigationController
        let controller = navigationController.viewControllers[0] as! AllListsViewController
        controller.dataModel = dataModel

        return true
    }

    ...

    func applicationDidEnterBackground(application: UIApplication) {
        saveData()
    }

    ...

    func applicationWillTerminate(application: UIApplication) {
        saveData()
    }

    func saveData() {
        dataModel.saveChecklists()
    }

}
3

3 Answers

1
votes

Try this and put it in your application(_:didFinishLaunchingWithOptions:) (hints are in the code comments):

// first find the UITabBarController
let tabBarController = window!.rootViewController as! UITabBarController

// then look at its viewControllers array
if let tabBarViewControllers = tabBarController.viewControllers {
    // the reference to the AllListsViewController object
    let allListsViewController = tabBarViewControllers[0] as! AllListsViewController
    allListsViewController.dataModel = dataModel
}

Edit regarding to the Comments (hints are in the code comments):

// first find the UITabBarController
let tabBarController = window!.rootViewController as! UITabBarController

// then look at its viewControllers array
if let tabBarViewControllers = tabBarController.viewControllers {

    // your AllListsViewController is in a NavigationController so get the right NavigationController
    // you can see the order of your added NavigationControllers in your storyboard in your case its the third
    // because tabBarViewControllers is an array the NavigationController where your AllListsViewController is, is at index 2
    let navigationController = tabBarViewControllers[2] as! UINavigationController

    // after you get the right NavigationController get the reference to your AllListsViewController
    let allListsViewController = navigationController.viewControllers[0] as! AllListsViewController
    allListsViewController.dataModel = dataModel
}
0
votes

Your main UITabBarController is not a UINavigationController. It inherits from UIViewController, just as UINavigationController. Which mean you can not write

let navigationController = window!.rootViewController as! UINavigationController

because you can not cast a UITabBarController in a UINavigationController. You could try

let tabBarController = window!.rootViewController as! UITabBarController

and use tabBarController afterwards.

0
votes

What you did wrong was here:

let navigationController = window!.rootViewController as! UINavigationController

The error says that a UITabBarController cannot be casted, or converted, to a UINavigationController, which is exactly what you are doing here.

In the storyboard, you said you connected 3 (table) view controllers to a tab bar view controller. And I assume that the app starting point is at the tab bar view controller. This means that window!.rootViewController is a UITabBarController!

Now that we know what is going on, let's see why this error occurred. The reason is simple, you are casting something to something that it isn't. window!.rootViewController is of type UITabBarController, right? So why are you casting it to UINavigationController? They are completely two different things!

So to fix the error, just cast the thing to UITabBarController instead:

let navigationController = window!.rootViewController as! UITabBarController

Also, I think you should change the variable names:

let tabBarController = window!.rootViewController as! UITabBarController
let controller = navigationController.viewControllers[0] as! AllListsViewController
...

Furthermore, you can be safer if you try this:

let tabBarController = window!.rootViewController as? UITabBarController
if let vc = tabBarViewController {
    let controller = navigationController.viewControllers[0] as! AllListsViewController
    ...
} else {
    print("The root view controller is not a tab bar controller!")
}

Notice the as? instead of as! there? This will return nil if the cast did not succeed. I then used optional binding to check whether it is nil. If it is, output a message or something.