my app starts with a tab bar controller which have 5 tabs. At start the first one in presented with its name but the other four don't have a name until I click on them. Then the name appears depending which language the user has.
How can I set the name of the tabs before the tab bar appears?
I am using storyboard. Is there a way to set title at the tab bar programmatically when all the rest is done with storyboard? I tried in the AppDelegate something like [FirstViewController setTitle:NSLocalizedString(#"Titel1", nil)];
But I got an error that there is no class method for selector setTitle.
Thanks.
I had the same problem today. I'm using storyboard too. In my case i used the following way.
I've created a new "Objective-C class" with the name
"MainTabBarViewController" as a subclass of "UITabBarController".
In my storyboard in "identity inspector" i changed "Custom class" to "MainTabBarViewController".
In the method "viewDidLoad" in "MainTabBarViewController" i added:
[[self.viewControllers objectAtIndex:0] setTitle:NSLocalizedString(#"home", nil)];
[[self.viewControllers objectAtIndex:1] setTitle:NSLocalizedString(#"statistics", nil)];
[[self.viewControllers objectAtIndex:2] setTitle:NSLocalizedString(#"settings", nil)];
[[self.viewControllers objectAtIndex:3] setTitle:NSLocalizedString(#"info", nil)];
I guess it is not the perferct way, but for me it works perfect.
I had a configuration with two tabs like this:
MainTabBarController : UITabBarController
+- MessagesNavigationController : UINavigationController
+- ContactsNavigationController : UINavigationController
In a configuration with Storyboard and ARC I overrode the initWithCoder: selector in the custom classes of my UITabBarController view controllers (in this case ContactsNavigationController) and initialized the tabBarItem.title there like this:
#implementation ContactsNavigationController
...
- (id)initWithCoder:(NSCoder *)decoder
{
self = [super initWithCoder:decoder];
if (self) {
self.tabBarItem.title = NSLocalizedString(#"Contacts", nil);
}
return self;
}
When using storyboards the iOS calls (id)initWithCoder: instead of -(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil when the storyboard view controller is initialized during UITabBarController launch. Also note that viewDidLoad doesn't get called until the view controller tab is selected from the tab bar.
In the app delegate, where you are creating the view controllers, set the title property here (rather than in viewDidLoad), for example:
vc1 = [[VC1 alloc] init];
vc1.title = #"List";
vc2 = [[VC2 alloc] init];
vc2.title = #"Map";
tabBarController.viewControllers = [[NSArray alloc] initWithObjects:vc1, vc2, nil];
If you take a look at the FirstViewController created by Xcode using the template Tab-Bar application based in the - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil method you can see something like this:
if (self) {
//check your language
self.title = NSLocalizedString(#"First", #"First");
self.tabBarItem.image = [UIImage imageNamed:#"first"];
}
So you have to check for your language and then set the title property, this will set the title on the tab bar and in the navigation bar.
Try this, in every view u have to use this method
Suppose this is you first view
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"homepage", #"homepage");
[self.tabBarItem setTag:0];
self.tabBarItem.image = [UIImage imageNamed:#"homepage"];
}
return self;
}
In you app delegate class write this code to add UITabBarController
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2,viewController3,viewController4,viewController5, nil];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
Add above code in
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {}
Related
I'm still new at this, so bear with me:
I created a new Window-based application in XCode 4 that happens to be a universal app. After that, I programmatically created a TabBarController with the associated view controllers (just basic views with 1-2 labels to help me identify each version (iPad, iPhone).
When I run the app and switch tabs, the viewDidLoad method does fire, the title appears correctly, but the visual view does not switch. It remains at the default MainWindow(device).xib file for each version. What am I missing here?
adding the tabs programmatically:
- (void) addTabs
{
//set up a local nav controller which we will reuse for each view controller
UINavigationController *localNavigationController;
//create tab bar controller and array to hold the view controllers
tabBarController = [[UITabBarController alloc] init];
NSMutableArray *localControllersArray = [[NSMutableArray alloc] initWithCapacity:2];
//setup the first view controller (Root view controller)
HomeViewController *myViewController;
myViewController = [[HomeViewController alloc] init];
//create the nav controller and add the root view controller as its first view
localNavigationController = [[UINavigationController alloc] initWithRootViewController:myViewController];
// add the new nav controller (with the root view inside of it)
// to the array of controllers
[localControllersArray addObject:localNavigationController];
//release
[localNavigationController release];
[myViewController release];
//setup the second view controller
MapViewController *secondViewController;
secondViewController = [[MapViewController alloc] initWithTabBar];
localNavigationController = [[UINavigationController alloc] initWithRootViewController:secondViewController];
[localControllersArray addObject:localNavigationController];
[localNavigationController release];
[secondViewController release];
tabBarController.viewControllers = localControllersArray;
[localControllersArray release];
}
and MapViewController.h is basic - there's really nothing there:
#import "MapViewController.h"
#implementation MapViewController
- (id)initWithTabBar {
if ([self init]) {
//this is the label of the tab button itself
self.title = #"Map";
//image goes here
//self.tabBarItem.image = [UIImage imageNamed:#"name_gray.png"];
//set the long name show in the Navigation bar at the top
self.navigationItem.title = #"Map View";
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Am I loading?");
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(#"Testing");
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
Now, there is no MapViewController.xib file, but the MapViewController_iPhone.xib and the MapViewController_iPad.xib files.
They Should be named: ~iphone, and ~ipad, and not: _iPhone and _IPad. The reason for this is that this is the format the reference says it to be.
Also note that the Simulator is NOT case sensitive, whereas the iOS device is, so make sure that you have the nib formatted as above, otherwise, it will only work on the Simulator.
Hope that Helps!
My UITabBarcontroller has two view controllers
-Favorites
-Keypad
I add these two controllers in an array in the order Favorites,Keypad,nil.
When the app is launched only the Favorites tab appears in the tabbar, I have to click the second tab for the "Keypad" (Title of the viewController) text to appear on the tabbar.
How do I make the tabbar have the title of both the view controllers at startup itself?
show us your tabbarcontroller init method. It should be straight forward -
-create 1 tabbarcontroller
-create 2 tabbaritems
-create 2 nav controller
-assign tabbaritems to nav controllers, using navcontroller.tabBarItem property
-use tabbarcontroller setViewControllers:animated: function to add nav controllers to tabbar, then add tabbar controller to window.
Try this in your ViewController where you load the tabController:
-(void)viewDidLoad
{
[super viewDidLoad];
// creating the tabController
UITabBarController *tabBarController = [[UITabBarController alloc] init];
NSArray* controllers = [NSArray arrayWithObjects: myViewController, nil];
myViewController.title = #"Title";
tabBarController.viewControllers = controllers;
[controllers release];
[self.view addSubview:tabBarController.view];
}
try this instead:
-(id)setup
{
UITabBarItem *item = [[UITabBarItem alloc] initWithTitle:#"xxxx" image:[UIImage imageNamed:#"xxx.png"] tag:0];
self.tabBarItem = item;
[item release];
return self;
}
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
[self setup];
}
return self;
}
My controller hierachy:
TabBaseController (UITabBarController)
SubclassedController
In my tabbasecontroller I have a navigation bar button, which flips the subclassedcontroller with the presentModalViewController method, to a second UITabBarController.
So my question is: why does not
self.parentViewController
work in the second UITabBarController? It is nil.
I am trying this in my viewDidLoad method in the second UITabBarController:
if (self.parentViewController == nil) {
NSLog(#"Parent is nil");
}
UPDATED
This is the method in the UITabBarController with the navigationItemButton that presents it
-(IBAction)openModalTabController:(id)sender {
if (self.nvc == nil) {
ModalTabController *vc = [[ModalTabController alloc] init];
self.nvc = vc;
[vc release];
}
[self presentModalViewController:self.nvc animated:YES];
}
This is the controller(UITabBarController) that I present modally:
Header:
#interface NewBuildingViewController : UITabBarController {
}
#end
Main:
#implementation NewBuildingViewController
- (id)init {
[super initWithNibName:nil bundle:nil];
ViewController1 *vc1 = [[ViewController1 alloc] init];
ViewController2 *vc2 = [[ViewController2 alloc] init];
ViewController3 *vc3 = [[ViewController3 alloc] init];
NSArray *controllers = [[NSArray alloc] initWithObjects:vc1, vc2, vc3, nil];
[vc1 release];
[vc2 release];
[vc3 release];
self.viewControllers = controllers;
[controllers release];
self.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
return [self init];
}
#end
I also want to add that this message is displayed in the console(warning) when flipping:
Using two-stage rotation animation. To use the smoother single-stage animation, this application must remove two-stage method implementations.
Using two-stage rotation animation is not supported when rotating more than one view controller or view controllers not the window delegate
It would be helpful if you were to show how you are presenting that second UITabBarController. Are you perhaps ignoring the following warning found in the UITabBarController class reference?
When deploying a tab bar interface, you must install this view as the root of your window. Unlike other view controllers, a tab bar interface should never be installed as a child of another view controller.
I have a uiviewcontroller with two properties: trackName and playerObject. PlayerObject also has a trackName property. I call this uiviewcontroller from my main uiviewController with this code:
SecondaryViewController *nextViewController = [[SecondaryViewController alloc] initWithNibName:#"SecondaryViewController" bundle:nil];
NSString *trackName = #"a track";
nextViewController.trackName = trackName;
[self.navigationController pushViewController:nextViewController animated:YES];
[nextViewController release];
In SecondaryViewController I override the initwithnibname method to set the trackName of the playerObject. I do this with this code:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
playerObject.trackName = trackName;
}
playerObject.trackName = trackName;
return self;
}
Finally my playerObject has all of the view data the SecondaryViewController will need. It looks like:
- (void)awakeFromNib{
NSString *s = trackName;
//more code relevant to the the view controller
}
When I debug, the trackName string in the playerObject is nil. I assume I'm doing something wrong. How can I have this value populated with the trackName I originally passed in the main uiview controller?
It seems like when you are initing the viewController the playerObject variable has not yet been set, could this be possible?
This can sometimes happen when you override initWithNibName:bundle:.
Instead use viewDidLoad to do setup. Apple guarantees all required setup is performed before this method is called (not the case with initWithNibName:bundle:).
I'd like to launch a modal view controller the way one does with 'ABPeoplePickerNavigationController' and that is without having to creating a navigation controller containing the view controller.
Doing something similar yields a blank screen with no title for the navigation bar and there's no associated nib file loaded for the view even though I am invoking the initWithNibName when the 'init' is called.
My controller looks like:
#interface MyViewController : UINavigationController
#implementation MyViewController
- (id)init {
NSLog(#"MyViewController init invoked");
if (self = [super initWithNibName:#"DetailView" bundle:nil]) {
self.title = #"All Things";
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"All Things - 2";
}
#end
When using the AB controller, all you do is:
ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
[self presentModalViewController:picker animated:YES];
[picker release];
ABPeoplePickerNavigationController is declared as:
#interface ABPeoplePickerNavigationController : UINavigationController
The other way to create a modal view as suggested in Apple's 'View Controller Programming Guide for
iPhone OS':
// Create a regular view controller.
MyViewController *modalViewController = [[[MyViewController alloc] initWithNibName:nil bundle:nil] autorelease];
// Create a navigation controller containing the view controller.
UINavigationController *secondNavigationController = [[UINavigationController alloc] initWithRootViewController:modalViewController];
// Present the navigation controller as a modal view controller on top of an existing navigation controller
[self presentModalViewController:secondNavigationController animated:YES];
I can create it this way fine (as long as I change the MyViewController to inherit from UIViewController instead of UINavigationController). What else should I be doing to MyViewController to launch the same way as ABPeoplePickerNavigationController?
I'd like to launch a modal view controller the way one does with 'ABPeoplePickerNavigationController' and that is without having to creating a navigation controller containing the view controller
But this is exactly what ABPeoplePickerNavigationController is doing. It isn't magic, it is a UINavigationController that instantiates a UIViewController internally (a UITableView that is populated with your address book contacts) and sets the UIViewController as its root view.
You can indeed create your own similar UINavigationcontroller subclass. However, within it's initializer, you will need to create a view controller to load as its root view just like ABPeoplePickerNavigationController does.
Then you can do what you are trying like this:
[self presentModalViewController:myCutsomNavigationController animated:YES];
In the code you posted:
#interface MyViewController : UINavigationController
#implementation MyViewController
- (id)init {
NSLog(#"MyViewController init invoked");
if (self = [super initWithNibName:#"DetailView" bundle:nil]) {
self.title = #"All Things";
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"All Things - 2";
}
#end
I suspect you are having NIB issues. there isn't a "rootViewController" outlet to connect. This is why you have a blank screen.
The initalizer you should be using internally is this:
self = [super initWithRootViewController:myCustomRootViewController];