can anyone explain what the difference is between PushViewController and presentModalViewController?
One major difference is that
pushViewController only works in navigation controllers
presentModalViewController works for all view controllers
A modal view is made so that it prevents you from doing anything except whatever it is that it wants you to do. You must do something specific to exit the modal state. The modal view also covers up the navigation bar.
When you use PushViewController, it's more flexible through the navigation bar. It doesn't require an extra action to exit to another view.
Difference in animation are
pushViewController will slide in your new view from right.
presentModalViewController will pop up your new view.
Related
I'm trying to create an app using storyboard which has 4 scenes:
ChooseLoginMethod
EnterLoginData
SuccessfulLogin
MainScene.
What I'm doing right now is the following: I have an UINavigationController which has ChooseLoginMethod as its root view. ChooseLoginMethod has several buttons (for different login methods) which are push segues to EnterLoginData. EnterLoginData has a push segue to SuccesfullLogin and SucessfullLogin has a push segue to MainScene.
The problem is that SuccessfulLogin and MainScene display the back button on the top bar, which makes no sense for the application.
I've tried:
Hidding the top bar on these two Views. Not successful.
Changing the segue to modal. Seems to work, but doesn't feel like the right thing to do.
So what I would like to do is create a segue which breaks the chain of Views which are on the UINavigationController's stack. Is there a proper way to do this in storyboard?
-- edit --
Maybe what I should do is replace the root view ( Set root view for UINavigationController ). This may work, but seems like a programming work-around for something that should be possible to be done in storyboard. Or maybe it is just me not getting the "iOS way of doing stuff".
You had to use setNavigationBarHidden before the viewcontroller appears on the screen, like in viewWillAppear.
But then you can't go back from "MainScene" to the "RootController". So you should do something like popToRootViewController after "SuccessfulLogin" and then pop "MainScene".
I think it's usually best to have your main scene be the root view controller. From its viewDidAppear method, you can present your ChooseLoginMethod controller modally, and from there do modal transitions to your other login controllers. When you get to the end, and you want to go back to the main scene just dismiss the modals from the root view controller -- this will dismiss the first one, and any that were presented from it:
[self.view.window.rootViewController dismissViewControllerAnimated:YES completion:nil];
I am creating a navigation base application. I need to display a tab bar too.
My mainWindow.xib contains:
UINavigationController,
UITabBarController.
UITabBarController has three UINavigationController with it.
On a condition-based algorithm, I am displaying the Navigation and the TabBar.
It's working well. The problem occurs when I want to move any inner view of TabBar: it shows navigationBar there (what I need) but it shows TabBar too. I want to remove the TabBar of all inner view. When I hide the tabbar it still occupy its space at the bottom of view. I had tried to reset frame of View and Window but nothing helped.
How can I hide tabBar and use its space in my view?
Is the logic I am using correct or not? If not, please tell how to correct it. If there is a tutorial it would be better.
You can try this:
yourInnerViewController.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:yourInnerViewController animated:YES];
The answer is that you can't and trying to force it will break apple's HIG and they'll most probably reject your app.
The way I got around it was to use [self presentModalViewController:animated:] instead of [self.navigationController pushViewController:animated:].
I know its annoying, but a tab bar controller is there to switch between sections of your app. Therefore it provides functionality outside of the context of the navigation controllers within it and therefore cannot be hidden (properly) from inside one of those navigation controllers.
First, sorry about my English, I know it's bad, but I'm trying to make it better...
Here is the issue: I'm making an app, with a view controller, with a lot of views... I want to make a button to go back to the main one. I think I have to dismiss the views I pushed. I dont know if that is necessary or if I can push it again directly. If it is, how can I do that? I've tried to put a dismiss method after the presentModalViewController one, but it didn't work.
Any help?
Thank you so much for your help ;)
It hard to tell from your question, but you may be confused by the navigation stack and the modal controllers.
A modal controller gets presented and dismissed using:
presentModalViewController:animated:
dismissModalViewControllerAnimated:
Navigation controllers are pushed and popped using:
pushViewController:animated:
popViewControllerAnimated:
So make sure you are using the correct method to pop or dismiss the view in question.
To present and dismiss a modal view you'll have to use delegation.
Here is an explanation for how to present and dismiss modal views.
Modal views are handled differently than views controlled by the UINavigationController or UITabBarController, which just push them onto a view stack or array of views.
I have an TabBar application with 4 tabs. All four tabs have navigation controllers. In the settings tab i have a table with a cell for "Feedback". When the cell is clicked a FeedBackView controller is pushed which contains a feedback form with a few fields. This has a textfield for Category. When the textfield is touched, a modal view controller (FeedBackModalView) is presented with a picker. In the viewDidLoad method of the FeedBackModalView controller I typed NSLog(#"%#", self.parentViewController). In the console it shows the parentViewController as TabBar controller. Why is that? Shouldn't it be showing the FeedBackView controller as the parentView since I'm presenting the modal view in that controller?
I hope i was clear.
Using presentModalViewController with UITabBarController has some issues, and I believe the internal behavior of the method has kept changing in recent SDK versions. The bottom line is, you are supposed to use the root view controller to modally present a view controller. In case you are using tab bar interface, that becomes the UITabBarController object.
In an old version of SDK, when I presented a modal view in a view controller inside a tab bar controller the modal view did not appear in full screen, which wasn't an expected or a documented behavior. Now a modal view seems to appear in full screen anywhere, and I wouldn't be surprised if [self presentModalViewController:animated:] method internally checks self and if it has non-nil parentViewController property, send the message to the parent view controller (which will explain your observation).
My memory is vague and perhaps somebody has to correct me. However, I still believe it's the straightforward thing to understand (and also maybe practice) presentModal... only works with the root view controller.
I'm working on a dual-iPad/iPhone application.
I'm having a problem that is occurring on the iPad only:
Root view controller is a UISplitViewController on iPad, UITabBarController on iPhone
A modal UIViewController can appear over the root controller
A modal UIViewController can appear over the previous modal controller
On iPad, modal controllers are using UIModalPresentationStyle.PageSheet
Everything works, except dismissing the topmost modal controller from the iPad--the method is called, but the modal view controller doesn't dismiss. I dismiss by calling DismissModalViewControllerAnimated from the previous modal controller.
Any ideas why this wouldn't be working on the iPad?
In all cases, I call PresentModalViewController and DismissModalViewControllerAnimated from the parent controller to work its child modal controller.
I'm using MonoTouch (you can tell by my casing of methods), but that is probably irrelevant. I can take answers in Obj-C as well.
UPDATE, following might make what it should do more clear:
Root => Modal A => Modal B
Dismissing Modal B should just return
to Modal A
Dismissing Modal A should just return
to Root
Are you sure you are dismissing the right view? Inside the modal view, lets say that you want to dismiss the view with a button click. In that button's method, you want to call the DismissModalViewControllerAnimated method. Just say
[self dismissModalViewControllerAnimated:YES];
Present the modal window from the root
when finished, dismiss the view from the modal view's controller.
It's hard to really diagnose the problem without seeing how you are trying to present and dismiss the controller, but that should work. You shouldn't need to do anything from the parent controller once the new view is displayed...
Found a workaround. All of these conditions had to be met to fix it:
First modal has default ModalPresentationStyle
Second modal has UIModalPresentationStyle.PageSheet
My second modal is displayed in the ViewDidAppear of the first. For some reason, I needed to call PresentModalViewController from BeginInvokeOnMainThread. (A one-liner in MonoTouch) This is a trick I learned from Windows development and message pumps. I have seen iPhone devs do similar workarounds with timers--this is much better.
I will post-back if we have trouble getting this through the app store. But for now, it is a good solution for us.