Search code examples
iosswiftuinavigationcontrolleruitabbarcontroller

Could not cast value of type 'UITabBarController' to 'ViewController'


The situation: when I press a button in rentViewController, it pops up a tableviewcontroller. If a specific cell has been pressed, it sends data to rentViewController. In order to send data from one view controller to another I needed the code

let rentViewController : RentViewController = self.presentingViewController as! RentViewController <- here is where the error shows up

so that tableviewcontroller could get access to the variables and functions from rentviewcontroller. I'm using

self.dismiss(animated: true, completion: nil)

to get out of the tableviewcontroller and back to the rentviewcontroller. However, it gives me an error "Could not cast value of type 'UITabBarController' to 'RentViewController'". I did some research and I think it's according to the orders of my view controllers but I'm not sure how to change it in a way that it works. My initial view is 'TabBarController' and the order after that is 'NavigationController' -> 'RentViewController' -> 'TableViewController'. If you have questions feel free to ask I can provide you more information.


Solution

  • Your viewController is being presented from UITabBarController. With approach you are using I believe you can access it like this (where index is index in UITabBarController of your UINavigationController containing RentVC):

    if let tab = self.presentingViewController as? UITabBarController, 
        let nav = tab.viewControllers?[index] as? UINavigationController,     
        let rentViewController = nav.viewControllers.first as? RentViewController {
    
            rentViewController.data = data
    }
    

    However, I would suggest using a delegate or callback block to pass data in this occassion.

    For delegate approach, first create protocol:

    protocol PassDataDelegate:class {
        func passData(data:YourType)
    }
    

    Then in TableViewController:

    class TableViewController: UIViewController {
        weak var delegate: PassDataDelegate?
    }
    

    And in RentViewController:

    extension RentViewController: PassDataDelegate {
        func passData(data:YourType) {
            //use data to suit your needs
        }
    }
    

    Before presenting TableViewController, in RentViewController, set its delegate:

    tableViewController.delegate
    present(tableViewController, animated: true)
    

    And finally, inside TableViewController, before dismissing, call delegate's method to pass data:

    delegate?.passData(data: <<someData>>)