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.
Related
After a modal view controller is dismissed, is there any delegate method called to bring the parent view controller to the front?
I ended up using delegation from Apple's View Controller Programming Guide for iOS :
http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ModalViewControllers/ModalViewControllers.html#//apple_ref/doc/uid/TP40007457-CH111-SW14
When it comes time to dismiss a modal view controller, the preferred approach is to let the parent view controller do the dismissing. In other words, the same view controller that presented the modal view controller should also take responsibility for dismissing it whenever possible. Although there are several techniques for notifying a parent view controller that it should dismiss its modally presented child, the preferred technique is delegation.
There was a good example in the CoreDataRecepies sample code when adding a recipe that fit what I was trying to do.
i.e., at the "same time" view[Will|Did]Disappear: is being called on the modal view controller as its view is being dismissed, the view[Will|Did]Appear: are sent to the view controller that is being revealed
the code in here should not really need to differ from the reveal code you used when it was first displayed,
if you need data passed back from the modal controller to the one that displayed it, generally the code that dismisses the modal controller lets the other one know
parentController.item = self.chosenItem;
[parentController dismissModal…
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.
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.
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 have a main screen that presents a modal view controller.
When the modal controller is done it calls a method on the parent to dismiss the modal and then display a different modal view.
The problem is that after dismissing the modal view controller (the view does correctly disappear) the subsequent presentModelViewController doesn't do anything.
If I look at the modalViewController property on the root controller I can see that after doing the dismiss it is still set to the old modal controller. As noted above the view is no longer visible and also if I profile the application there are no instances of that view in memory.
Any ideas?
The problem was that the modal controllers viewDidDisappear had not been called before I was adding a new modal controller.
Once I ensured that I only tried to add a new modal after the original modal viewDidDisappear had been called it worked ok.