Search code examples
iosobjective-cuitabbarcontrollersegueuistoryboardsegue

Passing Data to Tabbar Controller


I have a storyboard project and I would like to pass some data from a view into a tab bar controller, the information will be spread out between the tabs. After doing some research I found a very similar issue: iOS storyboard passing data navigationViewController but the only issue with this solution is that it was not transferring to a tab bar controller. I was wondering would I have to pass the data to each tab or can I pass it to the tab bar controller and then spread it from there? Thank you for your help in advance!

I am currently using the following; but, I get an error:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
     if ([segue.identifier isEqualToString:@"FoodPage"]) {
    NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
    UINavigationController *nav = [segue destinationViewController];
    FoodViewController *destViewController = (FoodViewController*) nav.topViewController;
    destViewController.Foods = [foodArray objectAtIndex:indexPath.row];
  }
}


Solution

  • In order to get a reference to your UINavigationController in your case, you have to do the following and specify the correct index to your tabBarController first:

    UINavigationController *nav = [self.tabBarController.viewControllers objectAtIndex:<THE_INDEX_NUMBER_FOR_YOUR_NAVIGATION_CONTROLLER];
    

    Once you have done so, then you retrieve a reference to your FoodViewController by specifying again the index number for it on your UINavigationController (i.e. if it's on top, then 0):

    FoodViewController *destViewController = (FoodViewController*) [self.nav.viewControllers objectAtIndex:0];
    

    Update:

    Now that I got a better idea what you would like to achieve:

    You are using UITabbarController in which your others controllers are embedded.

    Scenario / Example Case:

    Let say we had 2 view controllers, controller A and controller B, respectively, both are embedded in a UITabbarController.

    What we want:

    We are trying to change the text of a UILabel in controller B from controller A.

    First, declare a property in controller B in .h:

    @property(strong, nonatomic) UILabel *aLabelInControllerB;
    

    Second, declare a a property (or ivar) in your controller A:

    @property(strong, nonatomic) ControllerB *controllerB;
    

    Since you are using UITabbarController you don't need to use segue, you could simply get a hold of UITabbarController via self.tabBarController;

    Question: "how would I know then when my tab bar controller is tapped and then change the text of the label in controller B?"

    We do this:

    Set controller A as the delegate of UITabbarController by:

    In controller A .h, add:

    @interface <Your_Controller> : UIViewController <UITabBarControllerDelegate>
    

    In viewDidLoad of controller A:

    self.tabBarController.delegate = self;
    

    And in controller A .m, implement this method:

    - (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
    {
        self.controllerB = (ControllerB *) [tabBarController.viewControllers objectAtIndex:1];
        //In our example here, we only have 2 view controllers (A and B)
        //So, index 1 is where controller B resides.
    
        self.controllerB.aLabelInControllerB.text = @"Hello!";
        //This will change the text of the label in controller B
    }
    

    And as controller B appears, you will see that the text of the label will be changed to "Hello!"

    Setting a NSString in controller B follows the same procedure.

    Ex: self.controllerB.stringInControllerB = @"Hi from controller B!";

    Hope that helps.



    Update 2:

    Segue'ing from table view cell to a tab bar controller? Oki.. Here is the solution. I am only using one cell in my example, so should it become desired that you would like to have more cells in the future, I would leave that up to you to adjust.

    Let's take a look at the storyboard layout:

    In storyboard, control drag from your cell to the tab bar controller.

    Add a UINavigationController like in the picture.

    In your UITableViewController .m:

    Add 2 properties:

    @property (strong, nonatomic) UITabBarController *myTabbarController;
    @property (strong, nonatomic) YourFirstViewController *myFirstViewController;
    

    Just a friendly reminder:

    Remember to add:

    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    

    Add the following in your table view controller:

    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
        self.myTabbarController = (UITabBarController*) [segue destinationViewController];
        self.myFirstViewController = [self.myTabbarController.viewControllers objectAtIndex:0];
        self.myFirstViewController.stringFromTableViewController = @"Hi from TableViewController!";
    }
    

    And in myFirstViewController, add 2 properties in .h:

    @property (strong, nonatomic) NSString *stringFromTableViewController;
    @property (strong, nonatomic) YourSecondViewController *secondViewController;
    

    Like from the second edit above, have your first view controller to be still the delegate of UITabBarControllerDelegate and implement this method:

    - (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
    {
        self.secondViewController = (YourSecondViewController*) viewController;
        self.secondViewController.aLabel.text = self.stringFromTableViewController; 
    }
    

    Just like before, nothing needs to be changed in SecondViewController.

    I ran this myself; should be good to go for your setup.

    Enjoy.