This is the situation:
I have a tab bar with 2 tabs. Tab01 and Tab02.
In Tab01 I have a button which pushes repVC:
repVC.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:repVC animated:YES];
[(UIViewController *)[tabController.viewControllers objectAtIndex:0] setView:repVC.view];
[repVC release];
Inside repVC I have another button which pushes an MFMailComposerViewController:
MFMailComposeViewController *mail = [[MFMailComposeViewController alloc] init];
[self presentModalViewController:mail animated:YES];
[mail release];
The problem is: when mailView is shown(in Tab01) and I click Tab02, then back to Tab01, the mailView is hidden and even if I click the email button again, the view won't be presented.
So what I have is: Tab01.view -> repVC.view -> mail.view
For repVC, I use this line when I push the view so that even if I go switch tabs, that view will still be activated:
[(UIViewController *)[tabController.viewControllers objectAtIndex:0] setView:repVC.view];
But I can't do the same for mail because tabController is declared in another class which I cannot import. So I can't access the tabController and set the view for Tab01.
Hope the edit helped the understanding.
Hmm,
I still would suggest to use a Navigationcontroller. Would make things way easier, is conform to apple guidelines and suggestions and is pretty fast implemented. (Just create a Navigationcontroller, put the View of Tab1 as main view and hand it over to the TabbarController. Then for the mailView use [self.navigationController pushViewController:mail animated:YES]; Then the navcontroller "saves" the present view for you when u switch tabs)
But if for some Reason you have to use a modalViewcontroller you could either just deactivate the tabbar while the ModalView is shown or try to implement a switch or a simple if...else case in your ViewWillAppear where u check what screen to load.
Then Clean out the Window and load the right screen.
Hope you get the idea of what I mean, sometimes my way of writing seems to confuse people. ^^
A little more information would be great.
How did u set up your TabbarController?
How do u push the new view? Within a UINavigationController? If not, then do it with a navController, he should save the actual state of view and your problem should be solved.
If u already use a navController please post your ViewDidLoad and ViewWillAppear of the Viewcontroller of Tab 1
As #Amandir points out you could probably solve your problems by using a UINavigationController. I get a feeling that you are trying to abuse the modal view controller concept a bit and that's why it doesn't work as you expect. When you use presentModalViewController:animated: the intention should be that you are displaying a view that is modal, i.e. the user must interact and dismiss the modal view before she can continue.
What the paragraph above means that when you present a modal view controller it shouldn't be possible to use the tab bar. Since you are using the word push I'm guessing that you would like change the view of Tab01 while still being able to use the functionality of the tab bar. The problem is that there isn't any built-in method of pushing view controllers besides UINavigationController. persentModalViewController:animated: should only be used in case where you want a modal view, which on the iPhone means a full screen view.
The easiest way would probably be to use an UINavigationController and hide the navigation bar. Then you would get the functionality I think you are after. The other option is to manually add and remove sub views.
[self.view addSubview:repVC.view];
and
[repVC.view removeFromSuperview];
[self.view addSubview:mail.view];
You can use block animations if you want some fancy transitions.
Related
I have a Navigation controller in a storyboard, currently with two screens. Screen1 contains an opening logo and some buttons, and I have hidden the navigation bar at the top using:
[[self navigationController] setNavigationBarHidden:YES];
in viewDidLoad and viewWillAppear: (in viewWillAppear I have it set with animated:YES, so it slides off when coming back from other screens).
When I go to Screen2, I have:
[[self navigationController] setNavigationBarHidden:NO animated:YES];
in the first view controller's viewWillDisappear, and the navigation bar slides in all nicely when that view comes on to the top of the navigation stack.
Problem is, when I tap back, the navigation bar animates off the right side of the screen, but Screen2 stays there, revealing another navigation bar underneath!
I can then tap back again and it will push Screen2 off and the main screen shall return, but this is not behaviour I want to pass on to any users, obviously!
Anyone had this issue before, or have any points on what might be the culprit?
Edit: I just found an error appearing when I run the iOS Simulator:
2011-11-02 19:29:13.548 TestHTML5[10261:f803] Unbalanced calls to begin/end appearance transitions for <LessonViewController: 0x6c5e960>.
This happens when I click the button to go the the second view (LessonViewController).
Hopefully that might be the thing to crack this, anyone know?
I found my IBActions, which contained:
SecondViewController *X = [self.storyboard instantiateViewControllerWithIdentifier:#"X"];
[self.navigationController pushViewController:X animated:NO];
on each were causing the view to double up or something like that. When I commented these two lines out in each IBAction, the problem disappeared.
Thanks heaps to #CodaFi for helping me through possibilities for this, to be honest, this solution doesn't make sense to me, even thought I can see it working here.
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'm writing my first iPhone app and I am trying to figure out how to have a MasterView and DetailsView like in the example. However, instead of using a TableView, I want to use a button on the MasterView to go to the SignUpView. I want the MasterView to NOT have a navigation bar but the SignUpView needs to have one.
I have tried putting a NavigationController into the MasterView using the interface builder. This doesn't seem to do anything at all ... I.e. I make the following call:
[self.navigationController pushViewController:signUpViewController animated:YES];
And nothing happens. The SignUpView is never shown.
So then I declared a NavigationController in the AppDelegate. The above call in the same function that it was in before (button handler, button is in MasterView) works now! It takes me to the SignUpViewController.
however, the issue is, when I press back on the navigation bar in the sign up view, the navigation bar shows up again in the MasterView. I tried to set
self.navigationController.navigationBarHidden = YES;
in viewDidLoad and viewDidAppear, but that causes a black bar to appear in the transition from SignUpView to MasterView.
I tried to not set it in one of the two, and that causes the animation to go smoothly, but the navigation bar shows up in the MasterView.
I feel like this should be pretty simple to do ... but I'm at my wits end trying to figure this out. Some help would be really appreciated!
Thanks.
Probably not the answer to your question, but just a small suggestion. In the many apps that I have come across, a sign-up/sign-in view is generally displayed as a modal view (on top of your master view) with a 'cross' in the top-right corner to dismiss it. Probably it results in a better user experience.
Also, did you try self.navigationController.navigationBarHidden = YES; in the MasterView's viewWillAppear ?
HTH,
Akshay
I had this problem too, until I discovered setNavigationBarHidden. You will probably want to use these in viewWillAppear/viewWillDisappear or viewDidAppear/viewDidDisappear. You don't want to call this in viewDidLoad because that is only called once when the view is initialized, not every time it appears.
To hide:
[self.navigationController setNavigationBarHidden:YES animated:YES];
To show:
[self.navigationController setNavigationBarHidden:NO animated:YES];
So, I am using a RootViewController from which you can display first ViewController Categories and then from Categories you display next ex. Music
RootViewController -> Categories -> Music
In RootViewController I use this
[self presentModalViewController:categoriesView animated:NO];
to present the modal view and then dismiss it from Categories with
[self dismissModalViewControllerAnimated:NO];
From Categories to Music I use again
[self presentModalViewController:fruitView animated:NO];
to present the Music modal view and then dismiss it in music with again the same as above.
Is there a possibility to dismiss two modal views? I want a method that leads from Music back to RootViewController, dismisses both last modal views.
Any ideas?
Hi Use this Following code[[[self presentingViewController] presentingViewController] dismissModalViewControllerAnimated:YES];
Are you sure you want to use modal views for this? It sounds like what you're trying to do is better solved with a UINavigationController, where you can push and pop view controller's in a stack (and there's a popToRootViewControllerAnimated: message you can use).
This is how drill-down navigation is idiomatically handled in iOS (in the iPod, Notes, Contacts, Videos, Photos apps for example).
There's sample code for this in Xcode, I believe.
UINavigationController has a popToRootViewControllerAnimated: method, which per the documentation:
Pops all the view controllers on the
stack except the root view controller
and updates the display.
Use popToRootViewControllerAnimated method of UINavigationController.
[self.navigationController popToRootViewControllerAnimated:YES];
What you're talking about here, going from more general to more specific views, is better handled with a UINavigationController pushing and popping views. These are the views which slide left and right on the screen. Pushing means it slides in from the right (and shows a new, more specific view). Popping slides back to the right and shows a more general view.
A modal view controller is the one that slides in from the bottom of the screen. Look at the iPod app on your device for the way to handle this.
I use a nice utility method to do this... see here:
How to dismiss the two or more dismissModalViewController?
Use This, In music view write this for dissmiss 2 view .
[RootViewController dismissModalViewControllerAnimated:YES];
Here RootViewController is an object of RootViewController
Hope this will help u.
The main functionality of my app is controlled by a UITabBarController. However, I need to load a View that has a UINavigationController. When I return to my UITabBarController using
self.tabBarController.selectedViewController = [self.tabBarController.viewControllers objectAtIndex:0];
My UITabBarController no longer responds to clicks. It seems like the View does not have focus.
However, if I use this code to switch back to the UITabBarController:
[window addSubview:tabBarController.view]
My buttons will respond. I feel like "addSubview" is less efficient because I never remove the view from the window and therefore it must be adding a second copy of the view to the stack. Am I correct? Is there a way to use the first method and make my buttons respond? Please let me know.
It sounds like maybe you're presenting the Nav Controller incorrectly. You definitely shouldn't be adding views directly to the window. You want to present it using
[myTabBarController presentModalViewController:myNavController animated:YES];
When you're done with the nav controller you dismiss it with
[myTabBarController dismissModalViewControllerAnimated:YES];
and everything should work.
BTW, this is all documented in the docs for UIViewController and the "View Controller Programming Guide for iPhone OS" document.