I got a tabbed application like this:
and already set up everything like it should look, but it won't function yet. I already googled my problem and they said you first need to set up a NavigationController with the table view as rootView and then the NavigationBar but I really couldn't figure it out. Hope someone of you can help me.
Based on your response to my comment on your question here is what you should be doing:
First off, in order to make it look like the settings app table, you will need to change the style of your UITableView to UITableViewStyleGrouped.
Your hierarchy will consist of the following:
The viewcontroller that is actually added into your UITabBarController viewControllers array(since I see you have a tabbar as your lowest level of navigation) should be an UINavigationController. The root viewcontroller of the navigation controller should be the uiviewcontroller subclass you made that contains your table view. (let's say it's called SettingsViewController)
SettingsViewController *settingsViewController = [[SettingsViewController alloc] init];
UINavigationController *settingsNavController = [[UINavigationController alloc] initWithRootViewController:settingsViewController];
You will probably need to create a different UIViewController subclass for each type of detail pane you're going to want (if they have different functionality).
In the didSelectRowAtIndexPath UITableViewDelegate function, you will create the appropriate detail viewcontroller and push it onto your navigation stack.
Let's say you have a volume settings view controller as an example. The following is the code you would have in the function I just mentioned. Keep in mind you also need to actually check the index and/or section of the selected row to figure out which detail view should be shown.
VolumeSettingsViewController *volumeSettings = [[VolumeSettingsViewController alloc] init];
[self.navigationController pushViewController:volumeSettings animated:YES];
By default, this will function pretty much like the Apple Settings app navigation. The navigation bar will automatically have a "back" button to take you back to the settings view.
If you are using a Storyboard, select your view controller, go to the "Edit" menu and choose, "Embed in Navigation Controller."
If not using story boards, assuming this will be done in code, you need to create things in a reverse order of their hierarchy - something like this:
Create an instance of the Einstellungen tab's TableViewController using initWithNibName:
Create a UINavigationController using initWithRootViewController: and setting the Einstellungen as the root
Create a UITabBarController and set your navigation controller as one of the view controllers of this tab bar controller
Add the tab bar controller as a subview to the main window in your application delegate
This will create this hierarchy:
Tab bar controller
->view controller: Navigation Controller -> root view controller: Einstellungen
Related
I would like to add a TabBar to an existing view-based application I already started just to allow the user to switch to other parts of the app like the "About" section and another section entitled "Saved Searches" to display a navigational content (saved searches list > specific search result > product details).
Any idea on how to do this ? All tutorials I found point me directly to a TabBar template.
Thx for helping,
Stephane
You could start off with the UITabBar Application Template and you'll realize it's very easy to do:
In your UIApplicationDelegate class, in the method
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
Instantiate a UITabBarController like this:
UITabBarController *tabBar = [[UITabBarController alloc] init];
Then you set the view Controllers that will appear on the tab bar:
tabBar.viewControllers = viewControllers;
Which is a NSArray you can previously create with your UIViewController subclasses:
NSArray *viewControllers = [[[NSArray alloc] initWithObjects:vc1, vc2, vc3, nil] autorelease];
After this, you only have to set it as the root view controller of the window, or add it as a subview (it has the same effect, but the first approach doesnt work prior to iOS 4)
self.window.rootViewController = tabBar;
or
[self.window addSubView:tabBar.view];
And then
[tabBar release];
To achieve the kind of navigation that you say in your question, the view controllers you set to the tabBar should be instances of UINavigationController, which are very easy to create like this:
UINavigationController *vc1 = [[UINavigationController alloc] initWithRootViewController:firstViewControllerPage];
And inside them, you can push (navigate to) other view controllers doing:
[self.navigationController pushNavigationController:anotherViewController animated:YES];
Hope this brief review of it makes it a bit clear :)
You can create a new UITabBarController, and add it's view as a subview of your applications window. Then, add your other view controllers (for your "About" and "Saved Searches" sections) to that tab bar controller.
This can be done most easily in Interface Builder. In your MainWindow.xib, drag a Tab Bar Controller object onto the canvas. This will automatically create a tab bar with two items (one for each of the view controllers added). For each view controller under the tab bar controller, go to the identity inspector and change its class to your custom view controller subclass. Then, show the attributes inspector and there is a field "NIB Name" - again, set this to the appropriate nib name. Your custom controller views will then be loaded from their corresponding nib files. All that's left to do is name each tab in Interface Builder, and give it a graphic.
You can also do this programmatically if you don't like IB, by assigning the custom view controllers to the tab controller's viewControllers property, and assign a selectedViewController.
Hope this helps.
EDIT
Thought it might be helpful to show a little hierarchy! Your MainWindox.xib structure might look something like this:
AppDelegate
UIWindow
UITabBarController
UITabBar
AboutViewController (view loaded from "AboutViewController.xib")
Tab Bar Item - About
UINavigationController
Navigation Bar
SavedSearchesViewController - Root View Controller (view loaded from "SavedSearchesViewController.xib"
Tab Bar Item
And push appropriate view controllers from SavedSearchesViewController as normal to provide navigation content.
I would like to combine UITableView and UINaviationController in an app but as a newbie most apps I've seen just send you straight to the results view (UITableView). But, I guess a "normal" search application does not assume you have the results on the first screen. There should be a search form on first screen with input fields and a button that triggers the search process and show some results and navigation.
So, I'm just trying to replicate this normal behaviour in my app. I've already made the search form (no navigation shown on it, of course) and a seperated View called "ListingViewController" with its related View and containing a UITableView and where I think I should add the Navigation...The next idea will be to make a DetailViewController and possibly and ListingMapController to show the listing in a GoogleMap.
So, where I'm stuck at is how to add this Navigation Controller ?
Some suggested me to add it in the SearchViewController delegate...
But I don't want a navigation on search form of course...
Some suggested me to open the Navigation controller modally...
But, I"m also planning at adding a Tab Bar to allow user to see other informations (like About,etc...) and with a modal Nav controller I don't know if they will still see the bottom Tabbar...
Any suggestions? What do you think is of best practices especially to avoid my app of being rejected by Apple?
Thx in advance for reading and helping!
Stephane
You could init the navigationController with your View Controller as the root view Controller. Then hide the navigationBar (if you need to). You would then add the navigationController.view as the subview. This will basically look like the original view controller. Then you can pushViewController: animated: to push the results view Controller.
So, for example in your AppDelegate (or in the proper view controller):
Create a property and ivar for a UINavigationController and hook up its outlets in interface builder. Then set your search controller as the root view controller for the nav bar, and add it as a subview.
MySearchViewController* searchController = [[MySearchViewController alloc] init];
self.myNavigationController = [[UINavigationController alloc] initWithRootController:searchController];
[searchController release];
self.myNavigationController.navigationBarHidden = YES;
[self.window addSubview:self.myNavigationController.view];
[self.window makeKeyAndVisible];
Then of course in your searchController, you would simply say:
ResultsViewController* myResultsViewController = [[MyResultsViewController alloc] init];
//You may want to create another init method and pass in some arguments like an array:
// [[MyResultsViewController alloc] initWithResults:results];
then push the viewController
//This is in your search controller class
[self.navigationController pushViewController:myResultsViewController Animated:YES];
[myResultsViewController release];
from the results viewController, to get back you pop the view controller off of the navigationController view controller's stack.
//In results view controller perhaps in some IBAction for a back button:
-(IBAction)backButtonPressed:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
I have a tableView and want to add a new viewController so that when the user selects an item the new view shows an image and the bar at the top will allow the user to go back to the tableView.
This navigation bar at the top will be present in both views. Is it also possible to add a button e.g. share to it and link my own actions to the button?
Thanks.
Your tableView should live inside a UIViewController subclass that is itself inside of a UINavigationController. You can get this structure set up for you by selecting the "navigation-based" app in the project creation wizard. Or you can create this structure yourself in code. In your app delegate, create a UINavigationController, and set your app's first ViewController as the root view controller. Then pushing and popping view controllers is easy, just call:
MyDetailVC *vc = [[[MyDetailVC alloc] initWithNibName:#"MyDetailVC" bundle:nil] autorelease];
[self.navigationController pushViewController:vc animated:YES];
EDIT: so, to clarify, you don't "add navigation controllers to existing views," you "push and pop instances of your view controllers on to the navigation controller's stack."
I have a view based app that works well. (In other words, I'm not going to start over with a Navigation-Based App template.)
It's an immersive app of sorts and I'm trying to add a Table View that loads in a new view when a button is pressed.
The loading the nib part works, but I can't seem to be able to add a navigation controller to the new view. I want to see a navigation bar on top with a done button and an edit button. Also, I want to the Table View entries to be empty.
I added a new file like so:
File-> New File -> UINavigationController subclass. I checked the UITableViewController Subclass and With XIB for user interface.
All I see when the view is pulled up is a blank Table View. I am able to customize things in the view controller.
What can I do to make the table show a navigation bar and be editable? I need some direction here please.
EDIT: I'm working with the latest Public SDK. (XCode 3.2.2)
The navigation bar usually comes with a navigation controller, not with the table view controller.
You can add the navigation bar manually, but that will require altering the table view, to change it to just a regular view with a table view inside of it, and changing your table view controller to be a regular view controller that manually handles the table view stuff.
The simpler alternative is to wrap your table view controller inside of a navigation controller before you display it. Something like:
MyTableViewController *myViewController = [[MyTableViewController alloc] init];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:myViewController];
[myViewController release];
//Now display navigationController instead of myViewController, using something like:
[self presentModalViewController:navigationController animated:YES];
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/