How do I navigate back to the previous page with a UITableViewController. I tried to show a navigation bar with navigation button at the top of the screen, but the navigation bar will not show. I know that you have to give the previous view a title but when I go to do that it does not show anything. Also, since it is a UITableViewController I am not able to drop a navigation bar and add a button to the main view. All I would like to do is display my lists and have the option to navigate back to the previous list with a single button in the upper left corner.
The problem you having with the NavigationController is that your tableViewController is not in the NavigationController hierarchy. Want you want to do this when adding the tableViewController:
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:yourTableViewController];
Then you can do this to add yourTableViewController:
[self.view addSubview:navigationController.view];
If you don't want the navigationBar to appear on the tableViewController just use:
self.navigationController.navigationBarHidden = YES;
in yourTableViewController viewWillAppear method.
When your going to add the view after the tableView you just use:
[self.navigationController pushViewController:someViewController animated:YES];
It's not enough to give the child view a title. You need to give the child view's navigation item a title before you present it. For example, in the parent view, before you push the the view to the navigation stack, do something like this...
[MyChildView.MyNavigationItem setTitle:#"A cool Title"];
For the navigation you are trying to achieve you should be using a UINavigationController. It already has the functionality you describe with the navigation bar and back button built into it.
To move to the next screen (which can be a UITableViewController) you use pushViewController:animated: and to move to the previous screen you use popViewControllerAnimated: (although the built in back button will do this for you).
I suggest reading the UINavigationController class documentation if you are not already familiar with it.
Related
The figure shows my storyboard, with segues as directed.
In the tabBar's landing viewcontroller (i.e. I), both tabBar and navBar are visible which is desired. However, if a segue is performed (from I) to go to another viewcontroller (here, II), I want only the navBar. I am able to hide the tabBar by using
self.tabBarController?.tabBar.isHidden = true
Next, I am able to achieve the desired result by adding navigation controller at the beginning as shown below.
This configuration will add a navbar to the viewcontrollers ahead (like splash screen) so I will have to hide the navbar in those viewcontrollers.
Is there other method that does not require to hide the bar(s) and achieve the desired effect?
You should go with your first approach. Tab bar controller have default property to hide bottom bar. See below sample code.
ViewController *viewController = [[ViewController alloc] init];
viewController.hidesBottomBarWhenPushed = YES; // This property needs to be set before pushing viewController to the navigationController's stack.
[self.navigationController pushViewController:viewController animated:YES];
This will hide your tab bar while pushing to any child controllers.
EDIT
You can also set hidesBottomBarwhenpushed from storyboard for your tabbar controller so you don’t have to write down any code.
I have a UIView (with identifierSplashScreen) which basically acts as a introduction view and displays a small animation. once the animation is completed i want the view to display a tabbar view which here in after will be the main view. no data of any kind is passed on from the first UIView to the second UIView(with identifier HomeScreen). I have seen most examples where the
secondViewController *svc = [self.storyboard instantiateViewControllerWithIdentifier:#"HomeScreen"];
[self.navigationController pushViewController:svc animated:YES];
but this Pushes the view controller and a navigation bar with a back button appears which I dont want. Also I am never going to Return to the Splash Screen. it would be great if one of you could offer any help.
Iam a biggener and not a expert iOS programeer, so a simple code example will be of great help.
Instead of pushing onto the navigation stack why not replace the stack?
eg.
[self.navigationController setViewControllers:#[svc] animated:NO]
You can do a push segue and not have a navigation bar... Select your navigation controller and on the 4th tab on the right uncheck "Show Navigation Bar"
On one of my views, when a button is pressed I call another view that is a SplitViewController. If this SplitViewController is called via one of these buttons I have special objects to add to the view. mostly just nav bar items, like a cancel button. This view can be accessed elsewhere and these items are not needed which is why there is the special condition.
However, when the user is done and i pop the ViewController back to the previous screen that was selected, the nav bar disappears on that screen. I am not setting it to hidden nor am I doing anything strange with the nav bar. Simply adding the SplitViewController then popping back.
Some code..
//declare the split screen VC
SplitScreenViewController *split = [[SplitScreenViewController alloc] init];
//set the flag that this VC is coming from a button, so we need the extra nav bar items
[split setIsFromButton:YES];
[self.navigationController pushViewController:split animated:YES];
now the call back is simply...
- (void)cancelSelectionBtnClicked
{
[self.navigationController popViewControllerAnimated:YES];
}
and when the view returns, the nav bar is gone.
any ideas?
edit it should be noted this exact same thing is done elsewhere the same way(as far as I can tell) and the nav bar is visible on return.
In your ViewController's viewWillAppear you can again make your navigationBar visible.
- (void)viewWillAppear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:NO];
}
I have seen various strange navbar behavior in UISplitViewController's, and in a few cases it was because the controller was not set as the rootViewController of the window as opposed to inside a navigation controller like you have set up.
I've come across this twice now.
Sometimes using the following line of code:
[self.navigationController presentModalViewController:aViewController animated:YES];
displays the view, but the navigation bar is then hidden.
I can write:
[self.navigationController setNavigationBarHidden:NO];
to my hearts content, everywhere I can think of with no effect.
Has anyone ran into this?
Am I doing something silly?
No, I ran into this as well. The problem is that when you present a modal view controller with a UIViewController based class, it does not extend the calling navigation controller's nav bar onto the modal. The modal view covers the entire screen. What I ended up doing to solve the problem was to create a UINavigationController and push the UIViewController based class onto it, and then do presentModalViewController to the navigation controller's instance.
like:
UIViewController *vc = [[UIViewController alloc] init];
UINavigationController *cntrol = [[UINavigationController alloc] initWithRootViewController:vc];
[self presentModalViewController:cntrol animated:YES];
[cntrol release];
That allowed me to have a nav bar at the top.
I am not sure if that will help in your particular case, the only other thing I would suggest is to replicate the behavior of the modal with a UIAnimation that stops 44px below the top of the phone. That would keep the original navigation bar visible.
#HeatMiser shows a great way to get around the "bug" surrounding the inability to display items on the nav bar. I'm not sure, however, if this is strictly a bug in Presentation, since modal operations ought to trump the underlying view's interface theme. Having the modal operation's theme mimic the underlying UI theme is fine, but wrapping the true modal view with a navigation view feels wrong to me (extra view object just to get a little more behavior).
Instead, the following worked for me and gives the same behavior as "New Message" does in the Mail program (on the iPhone).
In IB, place a UIToolBar at the top of the modal screen (mimicking the navigation bar) with "Cancel" and "Save" UIBarButtonItem's and a Flexible Space Bar Button Item in between to get the buttons to align left and right. Then, add a UILabel centered over the UIToolBar (The Font Helvetica, Bold, Size 18 appears to match the Navigation Bar Title). Connect the buttons to IBAction's on the modal's UIViewController, and you're done.
If there is a navigation controller active, then you should just use
[self.navigationController pushViewControllerAnimated:how];
to slide another view controller in, while giving yourself and the user into a consistent user interface complete with 'automatic' back button support.
Once a navigation controller is in use, presenting a modal view controller should only be done to enlarge the usable area on the screen. And then, you should really use a fancy animation to let the user know that you are stepping away from the "task" or "steps" that the navigation controller was embodying.
Maybe this is obvious, but once you're done with the modal view and want to dismiss it, you should do something like this in your modal vc:
[parentController dismissModalViewControllerAnimated:YES];
Where parentController is a reference to the vc from where you are presenting the modal view.
I'm trying to implement a UI structured like in the Tweetie app, which behaves as so: the top-level view controller seems to be a navigation controller, whose root view is an "Accounts" table view. If you click on any account, it goes to the second level, which has a tab bar across the bottom. Each tab item shows a different list and lets you drill down further (the subsequent levels don't show the tab bar).
So, this seems like the implementation hierarchy is:
UINavigationController
Accounts: UITableViewController
UITabBarController
Tweets: UITableViewController
Detail view of a tweet/user/etc
Replies: UITableViewController
...
This seems to work[^1], but appears to be unsupported according to the SDK documentation for -pushViewController:animated: (emphasis added):
viewController: The view controller that is pushed onto the stack. It cannot be an instance of tab bar controller.
I would like to avoid private APIs and the like, but I'm not sure why this usage is explicitly prohibited even when it seems to work fine. Anyone know the reason?
I've thought about putting the tab bar controller as the main controller, with each of the tabs containing separate navigation controllers. The problem with this is that each nav controller needs to share a single root view controller (namely the "Accounts" table in Tweetie) -- this doesn't seem to work: pushing the table controller to a second nav controller seems to remove it from the first. Not to mention all the book-keeping when selecting a different account would probably be a pain.
How should I implement this the Right Way?
[^1]: The tab bar controller needs to be subclassed so that the tab bar controller's navigation item at that level stays in sync with the selected tab's navigation item, and the individual tab's table controller's need to push their respective detail views to self.tabBarController.navigationController instead of self.navigationController.
The two previous answers got it right - I don't use UITabBarController in Tweetie. It's pretty easy to write a custom XXTabBarController (plain subclass of UIViewController) that is happy to get pushed onto a nav controller stack, but still lives by the "view controller" philosophy. Each "tab" on the account-specific view (Tweets/Replies/Messages) is its own view controller, and as far as they are concerned they're getting swapped around on screen by a plain-ol UITabBarController.
I'm building an app that uses a similar navigation framework to Tweetie. I've written a post about how to do this on my blog www.wiredbob.com which also links to the source code. It's a full template you could take and use as a basis for another project. Good luck!
It's possible to add a UITabBar to any UIViewController. That way you don't actually have to push a UITabBarController and therefore stay within the guidelines of the Apple API.
In interface builder UITabBar is under "Windows, Views & Bars" in the Cocoa Touch Library.
I do this in a couple of my apps. The trick to adding a tab bar to a navigationController based app is to NOT use a TabBarController. Add a Tab Bar to the view, make the view controller for that view a TabBarDelegate, and respond to user selections on the tab bar in the code of the view controller.
I use Tab Bars to add additional views to the Tab Bar's view as sub-views, to reload a table view with different datasets, to reload a UIPickerView, etc.
I was struggling for the past hour to implement a UITabBar because it would get hidden when I tried to display my view; then I found this post:
Basically, make sure you insert your new view below the tabbar, per this line of code:
[self.view insertSubview:tab2ViewController.view belowSubview:myTabBar];
In my app, the root view controller is a UINavigation controller. At a certain point in the app, I need to display a UITabBar. I tried implementing a UITabBar on a UIView within the navigation hierarchy, as some of the previous posts suggested, and this does work. But I found that I wanted more of the default behavior that the tab controller provides and I found a way to use the UITabBarController with the UINavigation controller:
1) When I want to display the UITabBarController's view, I do this:
MyAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.window.rootViewController = myUiTabBarControllerInstance;
2) When I want to return to where I was in the navigation hierarchy, I do this:
appDelegate.window.rootViewController = myNavControllerInstance;
This could be achieved by simply embedding the TabBarController in the Navigation Controller.
In the storyboard:
Drag a ViewController
Click on the ViewController's Scene
Click on editor >> Embed in >> Navigation Controller.
Drag a button on the same ViewController.
Drag a TabBarController
Connect the button on the ViewController to the TabBarController via push Segue Action.
In this case only the TabBarController's RootViewController would be in the Navigation Controller's stack. All The TabBarItems would have the Navigation Bar at the top and user can go to Home Screen at any time, irrespective of the selected TabBarItem
This could be done at any ViewController in the Navigation Controller's stack.
If it works, please suggest me how to increase the reputation so that I can post the images and the code in the next answer. :)
This is how i did it. This is actually pushing a tabbarcontroller onto navigation controller. It works fine. I didn't find anywhere in the documentation that apple doesn't support this way. Can someone give me link to this warning?
If this is truth, is it possible that apple refuses to publish my app to appstore?
-(void)setArrayAndPushNextController
{
MyFirstViewController *myFirstViewController = [[MyFirstViewController alloc] init];
MySecondViewController *mySecondViewController = [[MySecondViewController alloc] init];
myFirstViewController.array = self.array;
NSArray *array = [[NSArray alloc] initWithObjects:myFirstViewController, mySecondViewController, nil];
UITabBarController *tab = [[UITabBarController alloc] init];
tab.viewControllers = array;
[array release];
UITabBarItem *item1 = [[UITabBarItem alloc] initWithTitle:#"first title" image:nil tag:1];
UITabBarItem *item2 = [[UITabBarItem alloc] initWithTitle:#"second title" image:nil tag:2];
myFirstViewController.tabBarItem = item1;
mySecondViewController.tabBarItem = item2;
[self stopAnimatingSpinner];
[self.navigationController pushViewController:tab animated:YES];
[tab release];
[item1 release];
[item2 release];
}
I wrote a blog post on how I approached this problem. For me, using a modal view was a simpler solution than writing a custom tab-bar implementation.
http://www.alexmedearis.com/uitabbarcontroller-inside-a-uinavigationcontroller/