Im having a strange bug in my code while working on an app for iphone. I am creating a navigation controller and putting it within my tab bar controller and then when i move from my initial screen to a secondary screen the back button on the secondary screen points to itself. so when back is pressed it just reloads itself and then the next time it is pressed it goes back to the first screen.
UINavigationController *nav1 = [[UINavigationController alloc] init];
// create the initial views for each nav controller
SearchViewController *searchView = [[SearchViewController alloc] init];
searchView.title = #"Search";
//place all the viewcontrollers on the nav controllers ready to view
[nav1 pushViewController: searchView animated:NO];
//create tab bar out of above nav controllers
UITabBarItem *item = [[UITabBarItem alloc] initWithTitle:#"Search" image:[UIImage imageNamed:#"search.png"] tag:0];
nav1.tabBarItem = item;
UITabBarController *tbc = [[UITabBarController alloc] init];
tbc.viewControllers = [NSArray arrayWithObjects:nav1, nil];
//
[nav1 release];
above code is in appdelegate for initial set up of nav + tab controller
SecondScreenViewController *sVC = [[SecondScreenViewController alloc] init];
sVC.title = #"Screen 2";
[self.navigationController pushViewController:sVC animated:YES];
[sVC release];
above is the code in the search view controller that loads the second screen / viewcontroller to the nav controller. But the back button at the top of screen 2 has the word screen 2 in it and when i press it once it reloads itself and then the back button says search (which is the title of first screen) . this time pressing it brings it back to the first screen.
Im just confused why the back button displays the view controllers own title name and reloads itself. I dont have any other code in these screens really, they are just blank screens with labels displaying which screen is there while i learn how to use it correctly
In the Apple Docs for UINavigationController for the designated initializer
- (id)initWithRootViewController:(UIViewController *)rootViewController
it is stated that:
Every navigation stack must have at least one view controller to act as the root.
I would recommend trying to initialize your UINavigationController with a rootViewController.
TiltedWindmill, I've experienced that problem before. In my case, in my head, I wanted to do this:
( > = pushing view controller )
Start at MapViewController > Details About An Attraction for a clicked pin on the map > MapViewController > Then pushing another DetailsViewController.
In my MapViewController, this view controller was registered for a notification. Theoretically, I thought I was navigating like this Map > Details View Controller > Map > Details View Controller. The thing was, whenever I tapped on the pin on the map, the Notification was fired and both copies of MapViewController that was on the navigation stack responded to the notification.
As a result it pushed two copies of the same DetailsViewController. So the real navigation was like this:
Map > Details View Controller > Map > Details View Controller copy1 + DetailsViewController copy2
*> = Second details view controller was pushed ontop of the previous one but not visible to the eye.
When I went to press the back button, it popped DetailsViewController copy2 and showed the same view controller (DetailsViewController copy1).
I fixed it by telling my MapViewController to unsubscribe from the notification on the event viewDidDisappear.
Not sure if you understood that :P
Related
I have a MenuViewController and a UINavigationController sitting inside a ViewDeck, a framework for a side menu. You simply initiate like so:
ListingViewController* lvc = [[ListingViewController alloc] init];
UINavigationController* homeNavStack = [[UINavigationController alloc] initWithRootViewController:lvc];
MenuViewController* sideMenu = [[MenuViewController alloc] init];
IIViewDeckController* slideController = [[IIViewDeckController alloc] initWithCenterViewController:homeNavStack leftViewController:sideMenu];
Where the center view controller is my navigation controller, and the menu view controller is hidden on the left, and you must slide to the left to make it visible (similar to facebook's side menu).
There is a button in the side menu, that when pressed, needs to transition the app back to the navigation controller, and have it push a new view controller. Here is my code for this, inside MenuViewController.m:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if(indexPath.row == 0){
NSLog(#"check");
UserProfileViewController* userProfile = [[UserProfileViewController alloc] init];
[self.viewDeckController toggleLeftViewAnimated:YES];
[self.centerViewController pushViewController:userProfile animated:YES];
}
}
toggleLeftViewAnimated brings back the center view controller, hiding the side menu again. I have given the side menu a reference to the center view controller, and using this, I ask it to push a new view controller. However when this method is called, nothing happens after the center view controller comes back into view. Does anyone know why this won't work?
Check whether the self.centerViewController is a Navigation Controller instance that you have added as center view controller. You need to get the instance of Navigation Controller you have added in to the IIViewDeckController where now you are using self (which might be the MenuViewController). I think you need to write a method to get the navigation controller form the IIViewDeckController and after that pushing your userProfile will work perfectly.
I have created an application that have 9 screen and I have added tabbar in it which contain 4 baritem.
Now I have two problems -
1 => My last baritem is logout button, I don't want to display view controller for it, simply when user click this button then alertview should pop up and ask for logout and if user says yes then it will logout.
2=> How to display tabbar in that view controller that does not added in tabbar, because I have 9 screen and only 4 screen display in tabbar.
UPDATE
I said that I have 9 view controller in my app
like...
firstViewController
secondViewController
thirdViewController
fourViewController
|
|
ninthViewController
But my tabbar have only four view controller in baritem which are -
firstViewController
secondViewController
thirdViewController
fourViewController
Now, my other view controller does not display tabbar.
I dont know this is right way or not but you can do it like this...
first read this question that show how to display login and come back to home.
Now add this code in didFinishLaunchingWithOptions method
UIViewController * logoutVC =[[UIViewController alloc] init];
NSArray *viewControllersArray = [[NSArray alloc] initWithObjects:firstView, secondView, thirdView,logoutVC, nil];
self.tabController = [[UITabBarController alloc] init];
[self.tabController setViewControllers:viewControllersArray animated:YES];
[self.window addSubview:self.tabController.view];
And implement this delegate method of tabbar
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
//select the index where your logout button is
if ([tabBarController selectedIndex] == 3) {
NSLog(#"logout");
self.tabController.selectedViewController = fistView; //firstview is your home screen
//LOGOUT
LoginViewController * vc = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
vc.delegate = self;
[self.tabController presentModalViewController:vc animated:NO];
}
}
Your first question:
Don't do this, it's an abuse of tab bar controller. Each item on the tab bar controller should be a different view in your app, not an action. Find an appropriate place for a logout action button.
Your second question:
There are several ways to show a view controller that isn't one of the main VCs for the tab bar controller. It could be reached by:
being shown as a modal screen
as a popover
Update
To show a 'secondary' view controller that isn't a main VC of the tab bar, but still have the tab bar visible, you can present that secondary VC as a sub-viewcontroller of a main tab bar VC. In other words, present the view of your secondary VC as a subview of a main VC view.
I'm trying to present a TabBarController on top of another TabBarController. My application's MainWindow.xib looks like this:
Files Owner
First Responder
My App App Delegate
Window
TabBarContoller
+TabBar
+Nav Controller Subclass (a custom class)
+Navigation Bar
+Table View Contoller Subclass (custom class)
+Tab Bar Item
+Second View Controller (not yet hooked up)
I'm trying to display a xib file when an item is clicked in the TableView. This xib file has a TabBarController as it's main view, but when the view displays, the tab bar and navigation bar are both invisible. The code I'm using to display it is:
MyAppAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[delegate.customNavController presentModalViewController:customDetailEditViewController animated:YES];
If I use the code below to push the view controller onto the stack, I see the correct navigation bar, but the TabBar from the root view controller is shown instead of the one from the view which has been pushed.
[delegate.customNavController pushViewController:customDetailEditViewController animated:YES];
I even tried removing the TabBarController and manually implementing my own TabBar delegates but the same effect occurs (either no NavigationBar or TabBar, or the NavigationBar/TabBar from the root ViewController).
EDIT: I've uploaded the source to http://mi6.nu/tabcontroller.zip . I'd really appreciate it if someone with a bt more experience with iOS could take a look.
EDIT2: The closest I've come so far is presenting a modal view controller inside the first tabbar, so my view looks like this:
NavigationBar
[ ]
[ ]
[---View---]
[ ]
[ ]
TabBar from the pushed view
TabBar from the root view
To achieve this, I'm using:
UITabBarController *tabBarController = [[UITabBarController alloc] init];
UIViewController *directionsView = [[UIViewController alloc] init];
txtDirections = [[UITextView alloc]initWithFrame:CGRectMake(0,0,self.view.frame.size.width, self.view.frame.size.height)];
[directionsView.view addSubview:txtDirections];
IconPickerViewController *iconPicker = [[IconPickerViewController alloc]init];
tabBarController.viewControllers = [NSArray arrayWithObjects:recipeDetailEditViewController,directionsView,iconPicker, nil];
[directionsView release];
[iconPicker release];
MyAppAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[delegate.rootNavController presentModalViewController:recipeDetailEditViewController animated:YES];
This just complicates everything though, since a) It's not ideal as I have two tabbars and b) all controls (all of the editing controls) need to be in the TableViewController so their values can be loaded/saved to edit items. It would be much easier if the pushed view could handle loading/saving and appear on top of the root tabs.
Surely this must be possible?
This was an absolute nightmare, but I eventually got it working by presenting the view modally from the TableViewController when the add button is clicked:
[delegate.rootController presentModalViewController:recipeDetailEditViewController animated:YES];
delegate.rootController is the root TabBarController
The XIB file I'm presenting does not have a TabBarController, but rather a UIView, a Navigation bar and a TabBar. This appears to work when presented modally from inside a NavigationController.
Why are you putting everything in your main.xib?
Try moving the second tab bar out of the main window xib and instead put it inside the customDetailEditViewController.
I have a very simple question. I have a view controller. In the view controller, i have added few buttons. On button click I have to start a tab bar controller (each of which has navigation controller).
Code Snippet:
- (IBAction) pushNewsAlertsController:(id)sender {
//Create a navigation controller
UINavigationController *FirstNavController = [[UINavigationController alloc] init] ;
//create the view controller (table view controller)
FirstViewController *firstViewController = [[FirstViewController alloc] init];
[FirstNavController pushViewController:firstViewController animated:YES];
//Create a navigation controller
UINavigationController *secondNavController = [[UINavigationController alloc] init] ;
//create the view controller (table view controller)
SecondViewController *secondViewController = [[SecondViewController alloc] init];
[secondNavController pushViewController:secondViewController animated:YES];
// Set the array of view controllers
tabBarController.viewControllers = [NSArray arrayWithObjects:firstNavController, secondNavController, nil] ;
//Add the tab bar controller's view to the window
[self.view addSubview:tabBarController.view];
}
I am able to add the tabviews and navigation controller. The problem is I am unable to get back to the main view once the button is clicked.
Can anyone guide me on how to get back to the previous view so that I can click other buttons.
In this case, I would consider presenting the tab bar controller modally. It's a cleaner way of organizing your views in the same way the user interface is organized. You can just dismiss the modal presentation to go back to the previous view. Read View Controller Programming Guide for iOS about similar advice and examples.
Not sure if I get what you are trying to do, but if you want the tab bar controller view to disappear again, the only way would be the inverse of
[self.view addSubview:tabBarController.view];
which could be
[tabBarController.view removeFromSuperview];
I must say it looks like an odd construction you're building, but it may work nevertheless.
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.