Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

How to pass data across tabs in a tabBarController

I'm trying to access an NSMutableArray which was edited in hierarchyTableViewController in agendaViewController, I have tried the following approach but it didn't work, what else can I try?

UITabBarController* tabBar;

hierarchyTableViewController* source = [[hierarchyTableViewController alloc]init];

source = [tabBar.viewControllers objectAtIndex:0];

self.classArray = [[NSMutableArray alloc] initWithArray:source.classHierarchyArray];

NSString* item = [self.classArray objectAtIndex:0];

8 Answers

Hi there,

I've got 2 solutions for you...

For small amount of data you can try the following:

In your AppDelegate.h declare:

@property (strong, nonatomic) NSMutableArray *delegateMutableArray;

In your AppDelegate.m init the array like so:

AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
delegate.delegateMutableArray = [NSMutableArray array];

and delegateMutableArray will become accessible everywhere now.

Now in your hierarchyViewController.m

#import "AppDelegate.h"

and you can access and modify it now by using

AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[delegate.delegateMutableArray addObject:@"test"];

Now in your other tab bar view controller you do the same ( #import "AppDelegate.h" ) and you can access the array the same way you did in your source view controller.

AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSLog(@"%@", delegate.delegateMutableArray);
// for example

but keep in mind you can do this for small amounts of data. I've archived the AppDelegate and the two example view controllers in case you don't get it from my post and you can download it at: http://www.robert-bojor.me/dl/ex_1.zip

A more elegant solution would be to use the TabBarControllerDelegate and pass the data before the tab switch. You can do it like so:

FirstViewController.h

@interface FirstViewController : UIViewController <UITabBarControllerDelegate>

@property (strong, nonatomic) NSMutableArray *firstMutable;

@end

FirstViewController.m

#import "FirstViewController.h"
#import "SecondViewController.h"

@interface FirstViewController ()
@end
@implementation FirstViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    self.tabBarController.delegate = self;
    self.firstMutable = [[NSMutableArray alloc] initWithObjects:@"item 1", @"item 2", nil];
}

-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController{
    if ([viewController isKindOfClass:[SecondViewController class]]){
        SecondViewController *svc = (SecondViewController *) viewController;
        svc.secondMutable = self.firstMutable;
    }
    return TRUE;
}
@end

SecondViewController.h

@interface SecondViewController : UIViewController
@property (strong, nonatomic) NSArray *secondMutable;
@end

SecondViewController.m

@interface SecondViewController ()
@end
@implementation SecondViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"%@", self.secondMutable);
}
@end

NSLog outputs:

2014-03-31 01:57:07.352 TabBarValues[4753:60b] (
    "item 1",
    "item 2"
)

I would use the second approach since it's far much easier to implement and more elegant but because I like to have options I've included the first one as well. And speaking about options, a third option would be using NSUserDefaults, I believe.

Sorry but I misspoke, how do I do this in a UITabBarController? I tried to use the following code sample and then show the data in an alert view but the alert view doesn't show any data when run

-(void) viewWillAppear:(BOOL)animated { [super viewWillAppear:YES];

UITabBarController* tabBar = self.tabBarController;

hierarchyTableViewController* source = [tabBar.viewControllers objectAtIndex:0];

NSString* item = [source.classHierarchyArray objectAtIndex:0];

UIAlertView* alert = [[UIAlertView alloc] initWithTitle:item message:item delegate:self cancelButtonTitle:item otherButtonTitles:nil, nil];

[alert show];

}

what did I do wrong in this?

Hi,

In the second example I gave you, the FirstViewController and the Second ViewController were the views for a tabBarController. As far as I understood you want to pass an array that gets modified in the first tab to the second tab.

Following my previous comment you can also try saving and updating the array using NSUserDefaults and in this way it will be accessible across your app.

So I did everything to the t in your second example but when I make the NSLog call, it says "[null]" what would have caused this? I even tried to change the parameter in the delegate protocol from (UIViewController*) to (UITableViewController*) since it is a table but that didn't work either.

For a faster solve tell me your setup.

As far as I understand you have a TableViewController and a UIViewController both being used in a UITabBarController. You are trying to pass data from the table to the view or from the view to the table? Is the table triggering the view change in the tabs?

So my tab bar controller has two tabs which are both table views, and for each tab I have a navigation stack as the root view controller. So the order of controllers for each of the two tabs goes as follows: tab bar controller, navigation controller, table view controller and the hierarchy tab at index 0 passes a mutable array to the tab at index 1

Ive been trying to implement this, but my individual tab bar items are each nested inside of a navigation controller. so when I call [viewController isKindOfClass:[SecondViewController class]] i get back UINavigationController instead of my custom class that is on that stack. should i use the app delegate pattern or is there a way to fix that

NSUserDefaults for the win!! Thank you!!