I have this code in my table view controller (and delegate):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DetailStatus *detailViewController = [[DetailStatus alloc] initWithNibName:#"DetailStatus" bundle:nil status:[mStatuses objectAtIndex:indexPath.row]];
[[self navigationController] pushViewController:detailViewController animated:YES];
[detailViewController release];
[self.tableView deselectRowAtIndexPath:indexPath animated:NO];
NSLog(#"exiting didselectrow");
}
And in my DetailStatus class:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil status:(NSDictionary *)pStatus {
NSLog(#"I am being called %d", [pStatus objectForKey:#"id"]);
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// some stuff
}
return self;
}
The funny thing is, my DetailStatus is actually being initialised, in the console window, it even outputs "I am being called 000001" but strangely the view is not being pushed to the table view...
I've checked the nib name, and it's ok. I checked the DetailStatus heading file, it looks ok (like this):
#interface DetailStatus : UIViewController {
So does anyone know why the view is not being pushed to the window even if I've initialised it and pushed it?
UPDATE: I tried logging some debugging messages to viewDidLoad in DetailStatus, and it seems like the view is not loaded even though the class was instantiated... I wonder why.
UPDATE2: I have a feeling that this might be my navigation controller organisation that's wrong.. I have this following:
Login page -> customtabbar -> First table view -> DetailStatus
-> Second table view -> DetailStatus
I think I'm only maintaining one navigation controller in that hierarchy. I've never created other navigation controllers. I only push view after another.
Thank you everyone for the answers! I will give out the bounty soon, I'll let other people vote first before the bounty expires.
After looking at it,the scenario seems to be same like me.What I faced for the first time when doing Tab+Navigation.
I am sure that there is some problem with your Tab+Navigation based application.
Although it shows the Tab as well as navigation are not able to navigate the basic flow.And it is very difficult to solve your problem with such less code.
Instead of this, I had an alternate solution for the same:
Once you have a tab bar in a XIB, the easiest way to approach this is to drag a UINavigationController object over from the Library window (looks like a left nav bar button on a gold background) into the Tree View for your tab bar (the text only view, not the GUI). Place it under the tab bar, then drag your existing view controller under the tab bar controller instead of under the tab bar.
When you go to view that tab you should then see a navigation bar on the top of it... if you are loading the navigation controller from another xib, you'll modify the nav bar in the tab bar xib.
else you can below you can follow the best url for the same:
http://books.google.co.in/books?id=2yYlm_2ktFYC&pg=PA179&lpg=PA179&dq=navigation+with+the+tab+based+application+iphoneSDK&source=bl&ots=nf2YYjX5Am&sig=COpHj9wOtsDChQBglpsljSTsElw&hl=en&ei=3ZoFTeGSOI_tsgbc_Iz6CQ&sa=X&oi=book_result&ct=result&resnum=6&ved=0CDAQ6AEwBQ#v=onepage&q&f=false
http://www.youtube.com/watch?v=LBnPfAtswgw
Hope this will surely solve your problem.
Unless the UINavigationController is the immediate parent of your table view controller, [self navigationController] will return nil.
I'm unclear exactly where it lies in the view controller hierarchy, based on your explanation, but I suspect you might have your UITabBarController nested within the navigation controller, when it should be the other way around. If, by chance, you actually mean to push the tab bar off screen (and thus you do want the tab bar controller nested within the navigation controller), you will need to call something like the following:
UIViewController *parentViewController = self.parentViewController;
[parentViewController.navigationController
pushViewController:detailViewController
animated:YES
];
P.S. Once the push is working correctly, you won't need to deselect the tapped row, as UITableViewController does this automatically when the view reappears.
I not seen putting status on the end of the init of the view. Guessing that's something you added.
Dont you just need to do [self pushViewController etc instead of the navigationController bit
Could it be that the nib is not wired up correctly. I.e. In the nib there is no connection between the view and the controller so even though the controller is pushed correctly, the navigation controller cannot find the view.
Just a guess!
You need to implement like above In tab controller put navigation controller according to your tabs and in navigation controller you can put your tab item.And also you need to set tab bar item nib file.then on tapping a tab you get tab screen and because of navigation controller you can easily navigate.even you can navigate on the screen of any tab main screen.
This is the way which you need to implement.
It definitely helps you but you need some logical implementation.
Is your tableViewController directly pushed to the navigation controller or is there another viewController in between ? Check the value of [self navigationController] against the value of your navigationController (from the place your actually instanciate it)
Once check that have you initialized the First Tableview and Second TableView with Navigation controller or not.
While adding to the tabBar, have you added the UINavigationController or only the UIViewController object.
PM_FirstNavigationController *First_navController = [[PM_FirstNavigationController alloc] initWithRootViewController:FirstTableViewController];
tabBarController.viewControllers= [NSArray arrayWithObject: First_navController];
You have to add the view controllers to the tabBar's like that.
Then while calling the [self navigationController], it will give navigation controller object.
Regards,
Satya
Related
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"
My UIViewController calls a function on my rootViewController which then called popToRootViewControllerAnimated to return the view to the rootController. This all works - great!
Unfortunately the UINavigationItem (toolbar at the top) seems to display a mashup of both the rootViewController and the UIViewController that has just been removed.
What do I need to do? What have I done wrong?
The navigation bar doesn't remember changes that were made to it, so when you push a new controller, the navigation bar is altered to give the title of the new view controller, but it doesn't store what was there for the previous view controller.
You will need to recreate the items in the toolbar each time you come back to the view controller that has custom items.
You might be able to do this on viewWillAppear instead of viewDidLoad. I can't recall exactly, but you should recreate custom controls on navigation toolbar because it does not get preserved when a new view controller is pushed.
It seems that calling popToRootViewController from the rootViewController messes things up. TO rectify this I called the following from within the calling UIViewController
[self.navigationController popViewControllerAnimated:YES];
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 created View based application, here i need to navigate between views when button pressed.
so in first view controller i have created action for button pressed.
-(IBAction)loadSecondView:(id)sender
{
SecondView *sView = [[SecondView alloc]initWithNibName:#"SecondView" bundle:nil];
[self.navigationController pushViewController:sView animated:YES];
[sView release];
}
this code is not working, anything i am missing,
i can do this by [self.view addSubview:sView]; but i need navigation effect.
Thanks in advance.
You can't just hook a UIView instance to a navigation controller, that's not how they work.
Take a look at the "Navigation-based Application" template in Xcode, to learn how navigation controllers work.
You can use view controllers while hiding the navigation bar:
[[self navigationController] setNavigationBarHidden:YES animated:NO];
You can then map UIButton instances to selectors that push or pop view controllers, while keeping the navigation bar hidden.
These button instances are subviews of the view controller's view property.
Hiding the navigation bar can help provide the illusion that you are not using a navigation controller, while giving you all the functionality of the navigation controller.
Alex is right, if you create just a "View Based Application" project, no UINavigationController was created so when you push something on it nothing happen, that's normal.
You have to create a UINavigationController and make you main view its rootViewController, then you can push on it a new viewController.
I have got a solution for this,
In View based application the appdelegate file creates object for, view controller and added that view to main window, to do our task, delete the controller in mainwindow.xib and add a UINavigation controller,and create a object to it, and connect outlet to it,and then add this navigation controller view as a sub view,
its work fine.
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/