MoreNavigationController images disappearing on select - iphone

I have a UITabBarController which has been created programatically, which has 6 tabs. As such the MoreNavigationController is automatically created to take care of having more than 5 tabs. Everything looks fine when the MoreNavigationController is displayed, but when I select one of these rows to push the view controller on to the stack, the cell image (tab bar image) disappears. When I pop that view controller, the image remains hidden until the pop animation is completed, at which point the image suddenly appears again.
This is fairly old code and I wouldn't do it this way these days, but everything works except for this last little thing so I'm pretty hesitant to rip out all the code and do it another way. Can anyone suggest what I might be doing wrong?
An example of creating one of the tab bar view controllers:
InfoViewController* infoViewController = [[InfoViewController alloc] init];
infoViewController.tabBarItem.image = [UIImage imageNamed:#"90-life-buoy.png"];
infoViewController.tabBarItem.title = #"More Info";
infoViewController.title = #"More Info";
UINavigationController* infoNavController = [[UINavigationController alloc] initWithRootViewController:infoViewController];
[infoViewController release];
Creating the tab bar:
tabBarController = [[UITabBarController alloc] init];
tabBarController.viewControllers = [NSArray arrayWithObjects:outdoorsNavController, peopleNavController, citiesNavController, landscapesNavController, infoNavController, basicsNavController, nil];
[window addSubview:tabBarController.view];
EDIT: Doesn't seem to make any difference whether I use retina (#2x) images or not.

The issue is because you're wrapping your InfoViewController in a UINavigationController.
When you click on the table row in MoreNavigationController, the controller uses the tabBarItem in UINavigationController while it does its transition. Because this is nil (in your code), the image in MoreNavigationController disappears. When the transition finally finishes, MoreNavigationController picks up the tabBarItem in InfoViewController
Try this:
InfoViewController* infoViewController = [[InfoViewController alloc] init];
infoViewController.tabBarItem.image = [UIImage imageNamed:#"90-life-buoy.png"];
infoViewController.tabBarItem.title = #"More Info";
infoViewController.title = #"More Info";
UINavigationController* infoNavController = [[UINavigationController alloc] initWithRootViewController:infoViewController];
//Set the tabBarItem for UINavigationController
infoNavController.tabBarItem = infoViewController.tabBarItem
[infoViewController release];
Here's a video reproducing and fixing the issue:
Item 7 has an empty tabBarItem.image while Item 6 has tabBarItem.image set

I'm not sure, but have you tried setting the NavigationCotroller's .tabBarItem?

Not sure if I understand correctly, but on the top of my head here are some suggestions (The More Tab Bar item shouldn't disappear at all times, that is created automatically)
Have you tried subclassing your UINavigationController that is being used for the MoreController's place and set its tab bar items properties there, therefore making sure you have control over its lifetime ?
Subclass your UIViewController's that you wish to push onto the navigation stack and have them use the same tab bar item ?
Mimic the default functionality, create your own UITableViewController to act as the More Controller, and at each tap of the rows, do what you want, also in a custom way.
PS: Try setting images name without the .png extension. This way you will automatically load the #2x resource as well. Eg: [UIImage imageNamed:#"90-life-buoy"]
Link

Related

How to set a tabbarcontroller as rootview controller of UISplitViewController

my application needs the design similar to sybase ipad app which is here YouTube - Sybase Mobile Sales for SAP CRM on iPad
How can I set a tabbarcontroller as rootview controller of UISplitViewController.
When I try to do this, 8 tabitems are displaying without "More" button. so its overlapping items title. And it will display More button if more than 8 tab items.
As it is using width 320, How to set only 5 tabs visible at a time.
sample
array = [[NSMutableArray alloc] init ];
for(int i=0; i <10; i++){
TestTabController *cc = [[TestTabController alloc]init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:cc] ;
[cc release];
[array addObject:navController];
[alertNavController release];
}
mytabBarController = [[UITabBarController alloc] init];
mytabBarController.viewControllers = array;
splitViewConntroller = [[UISplitViewController alloc] init];
[splitViewConntroller setViewControllers:[NSArray arrayWithObjects:mytabBarController, detailNavigationController, nil]];
How can I set the detailController view as a controller in the tabbarcontrolller(rootController) at runtime -Any easy methods ?-.. We can see when user tap on a cell in the detailController view, it immediatly move to rootController and its detail will show in detailController
Any help/comments/suggestions would be grealy appreciated.
If you create a UISplitViewController based project from the project templates and then open the MainWindow.xib file in interface builder, you can then just drag a tab bar controller component from the Library palette onto the first view controller (the navigation controller) inside the split view controller. Then you should be able to just start adding view controllers to the new tab bar controller. You then just specify the view controllers you want to use for each of the tabs. I've created several projects this way and it works quite well.
Of course, I'm assuming Xcode 3 here. I'm not completely sure if it's the same in Xcode 4 if that's what you're using.
if I'm not mistaken, UITabBarController should always be the root view controller in all cases.
So you're going the opposite way.

NavigationController not displayed when used along with TabBarController

In my iphone app, i have a navigation Controller and a tabBar Controller.
The TabBarController has three tabs. In the second and third Tab the NavigationController are added to the viewControllers.
Problem :
In third tab viewController shows the NavigationBar but the in second tab viewController doesnot display navigationBar.
Things I have tried and checked:
1) I checked that all the connections in IB are done properly
2) I checked the size of frame for the view. It doesnot overlap the navigationBar.
3) I also tried using self.navigationController.navigationBar.hidden = NO;
But still it does not show the navigationBar in the second tab.
What should I do?
Please Suggest
Please Help
Thanks!!
We can't do much without looking at your code.
Assuming your TabBarController is properly connected in Interface Builder, you'll need something similar to this:
UIViewController *firstView = [[UIViewController alloc] init];
UIViewController *secondView = [[UIViewController alloc] init];
UIViewController *thirdView = [[UIViewController alloc] init];
UINavigationController *firstNav = [[UINavigationController alloc] initWithRootViewController:secondView];
UINavigationController *secondNav = [[UINavigationController alloc] initWithRootViewController:thirdView];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:firstView, firstNav, secondNav, nil];
Of course, have every view released afterwards.
Hmmm thats a problem i faced too.
If you look at your IB file ,you'll see that you can do a bit of tweaking and acheive it.
i'll post details as soon as i get time.
Oops!!! a big mistake on my part.I did not check the checkbox for "show navigation bar" in inspector for NavigationController. Hope this helps someone.

Custom UITabBarController

I want to customize the look and feel of the tab bar of a UITabBarController. I want to change the colors, the way the icon looks when they are selected, and also, most important of all, I want to reduce the size of the custom toolbar.
My approaches for this and the hurdles in it are:
A) The first solution which came to my mind was to create my own viewController which will act like a UITabBarController with buttons in the bottom and add this viewController to the window. Once when user taps a button at the bottom, swap the view in the viewable area with the new viewController's which corresponds to the button now tapped by user.
The problem with this strategy is: since I swap view's the corresponding viewControllers will not get these messages:
viewWillAppear
viewWillDisappear
viewDidAppear
viewDidDisappear
And all the rotation events
B) I could have used the accepted answer's approach in this thread:
Custom UITabBarController Problems with View Controllers and Views
But my tabBar's height is not the same as the default.
Due to the cited reasons above, I cannot use those approaches.
Having said this, I have no special requirement of More tab. I will be having only 5 tabs which will be displayed by the tab bar and hence the re-ordering of tab bar items is out of scope.
Awaiting suggestions and ideas.
I have never attempted something like this but as I see it, you are supposed to send those messages to your child view controllers manually.
It shouldn't be problem to send -viewWill/Did(Dis)Appear to the right controller at the appropriate moment. This is what UITabBarController does, too.
As for rotation events:
In shouldAutorotateToInterfaceOrientation:, forward this message to your child controllers and set your return value depending on their return values (UITabBarController only returns YES if all its child controllers return YES for the requested orientation).
Forward willRotateToInterfaceOrientation:duration:, didRotateFromInterfaceOrientation: and willAnimateRotationToInterfaceOrientation:duration: to the child controllers (at least to the currently visible one) when you receive them.
If you have set the autoresizing masks of your child controllers' views correctly, they you rotate and resize correctly when the system rotates your custom tab bar controller's view. (At least I think that's how it should work.)
Again, I'm not sure if this will work.
You can implement the following code for the creating the custom tab bar in that use to images using the CGRect make.further code is use for the creating the custom tab bar
-(void)applicationDidFinishLaunching:(UIApplication *)application {
// Add the tab bar controller's current view as a subview of the window
tabBarController.delegate = self;
tabBarController = [[UITabBarController alloc] init];
mainDashBoard = [[DashBoard alloc] initWithNibName:#"DashBoard" bundle:nil];
mainSearchView = [[SearchView alloc] initWithNibName:#"SearchView" bundle:nil];
mainMoreView = [[MoreView alloc] initWithNibName:#"MoreView" bundle:nil];
UINavigationController *nvCtr0 = [[[UINavigationController alloc] init] autorelease];
UINavigationController *nvCtr1 = [[[UINavigationController alloc] initWithRootViewController:mainDashBoard] autorelease];
UINavigationController *nvCtr2 = [[[UINavigationController alloc] initWithRootViewController:mainSearchView] autorelease];
UINavigationController *nvCtr3 = [[[UINavigationController alloc] initWithRootViewController:mainMoreView] autorelease];
UINavigationController *nvCtr4 = [[[UINavigationController alloc] init] autorelease];//[[[UINavigationController alloc] initWithRootViewController:nil] autorelease];
tabBarController.viewControllers = [NSArray arrayWithObjects:nvCtr0,nvCtr1,nvCtr2,nvCtr3,nvCtr4,nil];
nvCtr0.tabBarItem.enabled = NO;
nvCtr4.tabBarItem.enabled = NO;
[window tabBarController.view];
}

How to hide a tabbar at the app startup?

So, I want my app starts with a UIViewController(without seeing a tabbar), and then enter a UITableView with navigationbar and tabbar. the problem is that the Tabbar is visible at the app starts up, anyone can help on this will be very appreciated...
I think you should either send -presentModalViewController:animated: to your main UIViewController with the tab bar controller as an argument or just do this:
[myWindow addSubview: myTabBarController.view];
Make your app a navigation based application (rather than a tab bar based one) then add a tab bar on the UITableView.
There is help for adding the UITabBar here
I do it like this : in this case drawing a table view and map view (From the Locati application)
tabBarController = [[UITabBarController alloc] init]; // creates your tab bar so you can add everything else to it
searchTableViewController = [[SearchTableViewController alloc] init]; // creates your table view - this should be a UIViewController with a table view in it, or UITableViewController
UINavigationController *searchTableNavController = [[[UINavigationController alloc] initWithRootViewController:searchTableViewController] autorelease];
[searchTableViewController release]; // creates your table view's navigation controller, then adds the view controller you made. Note I then let go of the view controller as the navigation controller now holds onto it
searchMapViewController = [[SearchMapViewController alloc] init];
UINavigationController *mapTableNavController = [[[UINavigationController alloc] initWithRootViewController:searchMapViewController] autorelease];
[searchMapViewController release]; // does exactly the same as the first round, but for your second tab at the bottom of the bar.
tabBarController.viewControllers = [NSArray arrayWithObjects:searchTableNavController, mapTableNavController, nil]; //add both of your navigation controllers to the tab bar. You can put as many controllers on as you like
I found this pattern a long time ago. Sorry that I can't point at the original.
YOu then need to add the tabbarcontoller to the relevant view ([...view addSubView:tabBarController];) possibly setting frame first.

Having trouble with UITabBarControllers in Interface Builder

I'm building an app in which the root view/window is a tab-based view (created using the XCode wizard for creating a tab-based iPhone app), but there is also a point in the app where I want to create another tab-based view and present it modally.
I was having so much trouble creating the modal tab-based view in IB that I eventually just did it in code, kinda like this:
// *** In the event handler that causes the second-tab view to be presented ***
MyTabViewController *tabVC = [[MyTabViewController alloc] init];
[self presentModalViewController:tabVC.tabBarController animated:YES];
[tabVC release];
// *** Inside init() definition in MyTabViewController.m ***
UIViewController *vc1 = [[MyViewController1 alloc] init];
UIViewController *vc2 = [[MyViewController2 alloc] init];
tabBarController_ = [[UITabBarController alloc] initWithNibName:nil bundle:nil];
tabBarController_.viewControllers = [NSArray arrayWithObjects:vc1, vc2, nil];
tabBarController_.selectedIndex = 0;
This worked fine until I started trying to write to tabBarController_.tabBar.items to set the titles and images for the buttons, which it apparently doesn't want to let you do for a TabBar that is owned by a TabBarController, giving this error:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason:
'Directly modifying a tab bar managed by a tab bar controller is not allowed.'
So I tried going back to implement MyTabViewController using Interface Builder so that I could set the buttons up in there, but I can't figure it out. These are the steps I took to get where I am:
Created new class descending from UIViewController in XCode, and checked the "with XIB" option.
Dragged a TabBarController into the XIB (the one with the yellow ball behind it).
The thing I can't figure out is how to get the TabBar to take over the view. Right now the View that comes with the XIB automatically is empty, and I have this UITabBarController that is totally disconnected from it. If I try to drag the TabBar from within the UITabBarController into the View, it appears to make a new TabBar instead of positioning my TabBar into the view so that it occupies the whole view.
I apologise if I haven't explained this very clearly, but I'm really struggling to understand the linkage between the TabBarController and the View, i.e. can't figure out how to get the TabBarController to actually display.
Any help with this would be much appreciated. I have attached a screengrab from IB if that helps at all.
alt text http://www.shelltoesmusic.com/files/tabbar_ib.png
The tab bar controller picks up the labels and images for the tabs from the view controllers it manages. The label comes from the view controllers' title. The image comes from the view controllers' tabBarItem properties. You can set both of these up in the init method of MyViewController1 and MyViewController2.
- (id)init {
if (self = [super initWithNibName:#"MyViewController" bundle:nil]) {
self.title = #"My View Controller";
UIImage* anImage = [UIImage imageNamed:#"MyViewControllerImage.png"];
UITabBarItem* theItem = [[UITabBarItem alloc] initWithTitle:#"Home" image:anImage tag:0];
self.tabBarItem = theItem;
[theItem release];
}
return self;
}
Every view controller has a view property. The tab bar controller is also a view controller so it too has a view property. Add the tab bar controller's view property to the view that is currently blank.
Example:
[view addSubview:tabBarController.view];
See documentation if you have questions. It's very complete.