PDA

View Full Version : Accessing View Controllers through TabBarController




BlackWolf
Apr 9, 2009, 04:54 PM
hi,
I just started developing for the iphone and making good progress so far. I got totally stuck today when I tried to use a tabbar though

so what I did, I used the IB to built me an UITabBar-Interface. So I used a UITabBarController and populated it with two custom UIViewControllers. So far so good, it works fine. My TabBar gets shown and I can switch between my two views.

My Problem is: I'd like to access some properties of my custom UIViewControllers from the applicationDidFinishLaunching method, but it seems impossible to do. I tried to access the UIViewController class (FirstController) via

FirstController *controller = [[self.tabBarController viewControllers] objectAtIndex:0];

problem is, I soon discovered that the "viewControllers" property of UITabBarController is nonatomic, copy.
So this doesn't work because I get a copy of my view controller instead of a reference. Couldn't find any other way to do this.

to make a long story short: how can I access the view controllers of a TabBar in applicationDidFinishLaunching?

thanks!



eddietr
Apr 9, 2009, 08:40 PM
So the "copy" versus "retain" or "assign" semantics with properties refers to the setters, not the getters. (And besides, even if it were a copy of the array, it would be a shallow copy so it wouldn't affect what you're trying to do.)

The point being that you can get the actual viewController instances from the viewControllers array. If that's not working for you, then there is something else wrong.

BlackWolf
Apr 10, 2009, 04:44 AM
So the "copy" versus "retain" or "assign" semantics with properties refers to the setters, not the getters. (And besides, even if it were a copy of the array, it would be a shallow copy so it wouldn't affect what you're trying to do.)

The point being that you can get the actual viewController instances from the viewControllers array. If that's not working for you, then there is something else wrong.

kay, thanks for that info.

well, can't imagine what I'm doing wrong. You're right, when I use the predefined UITabBar-Project it works fine. For testing purposes I built a completly new project (Window-Based). I'll explain exactly what I did, maybe someone can find the mistake I did. I hope I can explain everything correctly, my english is not that good unfortunatly.

First I went into the IB:
1) Took my window and added a UIToolBarController
2) Gave the two items of the ToolBar the classes "FirstController" and "SecondController"
3) Set "NIB File" of the two items (or rather the two controllers linked to them) to "FirstView" and "SecondView"
3) Created two new nib files in my project, both of them "View XIB" templates. Named them FirstView and SecondView.
4) Set the File's Owner class of the views to FirstController and SecondController

Then I went into XCode ...
5) Added two "UIViewController" classes to my project and named them FirstController and SecondController
6) I added to my app delegate header:

@interface (...) {
UIWindow *window;
UITabBarController *tabBarController;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;

7) Added to my app delegate .m-file

#import "tabTestAppDelegate.h"
#import "FirstController.h"

@implementation tabTestAppDelegate
@synthesize window;
@synthesize tabBarController;

-(void)applicationDidFinishLaunching (...) {
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];

FirstController *con = [self.tabBarController.viewControllers objectAtIndex:0];
con.label.text = @"testing";
}

8) Went into FirstController.h and added an IBOutlet for an UILabel called "label" (I'll skip the code now since this part is just copy and paste really)

Back to IB ...
9) Linked "tabBarController" of the app delegate to my tabBarController
10) Linked "label" of my FirstController to a label that I dragged onto the FirstView
11) of course linked the "view" property of the two controllers to the views

And after that: same result. everything compiles, no errors, no warnings. my two views get shown - but the label is not changed to "testing"

ideas?

eddietr
Apr 10, 2009, 11:11 AM
I hope I can explain everything correctly, my english is not that good unfortunatly.


Really? I would have thought you were a native English speaker, actually. Your English is great.

So I see what the problem is. applicationDidFinishLaunching will be called before those other two nibs are loaded. So to do what you want, you would have to do it after that firstview nib is loaded. Like in your viewDidLoad in your first view controller, that would work.

BlackWolf
Apr 12, 2009, 09:11 AM
Really? I would have thought you were a native English speaker, actually. Your English is great.

So I see what the problem is. applicationDidFinishLaunching will be called before those other two nibs are loaded. So to do what you want, you would have to do it after that firstview nib is loaded. Like in your viewDidLoad in your first view controller, that would work.

thanks :D
I tested and you're right. I can access the properties from applicationWillTerminate, it works fine.
So when exactly are the nibs loaded? I tried adding a
[self myMethod];
add the end of applicationDidFinishLaunching but it seems the nibs are still not loaded when the application reaches myMethod.
I wonder how this works anyway, I use the tabBarController in applicationDidFinishLaunching and even add the tabBarController's view to my window - how can the nibs not be loaded at that time?

Anyway, when exactly are the nibs loaded? It's just that my app saves preferences and I want to set some switches etc. to on or off based on saved preferences. I thought the best time to do that would be applicationDidFinishLaunching, but it seems like I rather move these things to viewWillLoad or viewDidLoad, don't I?
The important thing is that I can save the state of the switches to the preferences in applicationWillTerminate and this seems to work.

thanks for your help so far.

eddietr
Apr 12, 2009, 10:25 AM
I wonder how this works anyway, I use the tabBarController in applicationDidFinishLaunching and even add the tabBarController's view to my window - how can the nibs not be loaded at that time?


So the view controllers are set up in the tabBarController, but each view controller doesn't actually need to load it's own nib until it actually has to show its view. So for performance and memory reasons, you'll notice the view controllers don't set up their own views until they have to. So for example, if you put some logging in viewDidLoad, you'll see that the second view controller won't load its nib until after the user has actually selected that tab.


...but it seems like I rather move these things to viewWillLoad or viewDidLoad, don't I?

viewDidLoad (on your view controllers) will be called after the nib has been loaded and all the outlets have been set. So if you need access to outlets on File's Owner (and any other outlets), this is the best place to do your initialization.