I have a view controller with the following method:
- (IBAction)pickLocation:(id)sender{
SearchLocationPickerViewController *modalView = [[[SearchLocationPickerViewController alloc] init] autorelease];
[modalView setModalTransitionStyle:UIModalTransitionStylePartialCurl];
modalView.searchVC = self;
[self presentModalViewController:modalView animated:YES];
}
This transitions perfectly fine, and displays the modal view controller as expected. However, when I dismiss the modal view using the following (executed from the modal view controller):
- (IBAction)closeLocationPick:(id)sender{
[self dismissModalViewControllerAnimated:YES];
}
The modal view transitions out as expected, but right at the end of the transition, the display will really quickly flicker SOMETIMES. It displays the modal view that was just displaying for a fraction of a second. This only happens maybe every three out of ten times of showing / hiding the modal view.
Any ideas on what could be causing this?
If I am reading your post correctly, one problem may be that you are dismissing the modal view from within itself. While this does work, it is not the way in which Apple prefers. I am making the inference that this may muck with the animation of the view as it is dismissed.
Your IBAction should be calling a delegate method in the modal view controllers parent, the one that created and presented the modal view controller originally. You define the delegate protocol in your modal view controller and adopt it in the view controller that makes the presentModalViewController: call.
Here are the relevant Apple docs on dismissing a model view.
Related
I currently have an application that does the the following:
S: Loads a view as a login screen to start with.
a: If login is successful I add a terms and conditions screen as a subview
b: If not successful I add a sign up form as a subview
F: Then I load the main part of my app on success of either of the a or b which is the part of the app where there is a navigation controller and a tab bar controller. This is set up in MainWindow.xib
S, a and b also have Nav bars but no navigation controllers as I didn't think I would need navigation control on the login screens.
However it turns out I do, I want to be able to have back navigation from both a and b to the initial login screen.
I have tried several ways of doing this including trying the following answers:
How to add navigation controller in View Based Application in iPhone?
How do you properly set up a secondary view to support a navigation Controller on the iPhone?
how to add navigation controller programatically?
But none of them work for me, they display the new Navigation controller over the login screen and dont load the a or b screens.
I'm guessing this is because I am adding them as subviews to my loginView and this is not the correct way to do this? My code is as follows:
if(self.tcSubViewController == nil){
TCSubViewController *_tcSubViewController = [[TCSubViewController alloc] initWithNibName:#"T&CView" bundle:[NSBundle mainBundle]];
self.tcSubViewController = _tcSubViewController;
[_tcSubViewController release];
}
[self.view addSubview:[tcSubViewController view]];
I'm guessing there's a fundamental flaw in the way my Login flows? I should be able to completely remove the LoginView and then display the Terms and conditions view without having to add it as subview, shouldn't I?
You need to dismiss the navigation controller to go back to.
To dismiss modal view:
1.Easy way: In your modal view in some method that you call to dismiss just add:
[self.navigationController dismissModalViewControllerAnimated:YES];
2.More complex way: Implement and delegate protocol on your modal view and make the view controller that presents the modal view the delegate of it. And in the delegate method dismiss the modal view. I do this way when I need to send data from modal view to the controller that present it.
Reference to this post
Navigation controller philosophy is that you add only navigationController.view as UIWindow subview and it wil manage the rest by itself. You only need to push/pop viewControllers and their corresponding views will be added/removed from screen automatically.
sample code from my current application:
HomeController *homeController = [[[HomeController alloc] init] autorelease];
self.controller = [[[UINavigationController alloc] initWithRootViewController:homeController] autorelease];
self.controller.navigationBarHidden = YES;
[self.window addSubview:self.controller.view];
[self.window makeKeyAndVisible];
and then to push next view you just add next controller:
[self.navigationController pushViewController:newController animated:YES];
I have a UITabbarController with a UINavigationController. The view in the NavigationController presents an MVC (AddClockNavigationController). This MVC has a nib with an view and an UINavigationController. The NavigationController.view is added as an subview to the MVC's view.
The NavigationController in my MVC has two buttons, an Cancel and an Done. When pressing either one of them the MVC should be dismissed.
The IBActions of these buttons are in the UINavigationController's view (AddClockViewController), but whenever pressing them the MVC does not dissappear.
If I put the actions into the MVC, it does disapear.
If I put the function in my MVC and call it from my viewController using [self.parentViewController myFunction] it does not disappear.
How can I get it to disappear from my view?
I guess my explenation is quite messy but I hope you understand it.
A view from my IB:
Best regards,
Paul Peelen
Edit
I have tried this with [self dismissModalViewControllerAnimated:YES];, [self.parentViewController dismissModalViewControllerAnimated:YES];, [self.navigationController dismissModalViewControllerAnimated:YES];, [self.parentViewController.navigationController dismissModalViewControllerAnimated:YES]; and, as stated, with a function in the parentView dismissing it. Nothing works.
When some view controller presents another one, it becomes a parent view controller. So if you want to dismiss your modal view controller, then you have to choices:
from the parent view controller call
[self dismissModalViewControllerAnimated: YES];
OR
from the modal view controller call
[self.parentViewController dismissModalViewControllerAnimated: YES];
You actually don't need the navigation controller (cause you don't push/pop any view controllers). Just add the UINavigationBar to your MVC and place buttons on it. Then add actions to them and do choice #2.
Your code is not working because navigation controller has no parent, as it wasn't presented as modal.
One situation is that dismiss{Modal}ViewControllerAnimated is called before presented viewController's viewDidAppear is called. In such situation, the presented is presented with animated == YES. and before the presented is fully appeared, it got dismissed.
To fix it, you need to check at the point of time for dismissing, check if viewDidAppear is called, if not, defer the dismissing in - viewDidAppear.
I have a confusion on canceling the modal views:
Case 1: I have a navigation view controller and I am presenting a modal view controller from this navigation view controller. Now, when I am to cancel this modal view from where should I call the dismissModalView method -- navigation view controller or the modal view controller?
Case 2: I have a modal view controller and I am presenting another modal view controller from first modal view controller. Now, when I am to cancel second modal view from where should I call the dismissModalView method -- frist modal view controller or the second modal view controller?
Will canceling it from a wrong place cause a app crash also?
An advisable way to handle modal view controllers is to us notifications to inform the class that presented it to release it. Generally, you use code similar to this to show a modal view.
SomeClass *yourViewController = [[SomeClass alloc] initWithNibName:#"SomeClass" bundle:nil];
[self presentModalViewController: yourViewController animated: YES];
[yourViewController release];
With the above code, your modal view should end up with a retain count of 1. When you dismiss it, the parent view will release it and it will be purged from memory. Your "close" button in your modal view should execute code that looks like this:
- (void)dismissSelf{
[[NSNotificationCenter defaultCenter] postNotifivationName:#"I'm done" object:self];
}
Back in your parent viewcontroller, ou should listen for this notification and then dismiss the modal view when the notification is posted.
That said, to answer your questions:
A modal view controller never dismisses itself. Post a notification and then let the navigation controller handle it.
You can't dismiss the first modal view until the second one has been dismissed. If you do, you will get a EXC_BAD_ACCESS error. Think of the second modal view as "inside" the first one. If the first is dismissed, the second one will be dragged away with it, but it hasn't been dismissed.
you should dismiss the modal view
controller.
you should dismiss it from the
second modal view controller.
the app crashes because when you trying to dismiss the modal view controller , the scope of corresponding view controller is lost, may be u released the view controller before dismissing
You always dismiss the modal view from the controller, where you presented it (with dismissModalViewControllerAnimated). So:
in the navigation controller
in the first modal view controller
I'm attempting to create an application that has a regular view shown on start-up. It acts as a introduction view with two buttons that give the user choices to sign or register. After clicking sign in I present the form with presentModalViewController. After they finish with this I want to dismiss the modal view, and swap the introduction view with a tab bar controller that is the regular application.
I'm having a lot of trouble getting this to happen animated though. I did manage to get the modal view to transition out with the new view below it, but then immediately the introduction view is reshown, and I'm not sure why.
In the delegate I'm running this:
[window addSubview:firstRunController.view];
Presenting the view is very standard
This is how i'm dismissing it and getting the behavior I said above:
QuestionMeAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[self dismissModalViewControllerAnimated:YES];
[delegate.firstRunController.view removeFromSuperview];
If you maintain views by navigationController, you can assign view controllers by - (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated.
I did swap views by re-assigning view controllers of navigation controller first, and then call dismissModelViewController to leave current view controller or navigation view controller.
I am having trouble getting my modal view controllers to display properly. I have a parent view controller that is the delegate for modal view A. In modal view A I am presenting modal view B, and having the delegate dimiss modal view A.
When modal view B appears it seems to display but the screen dims, and the UI locks up, but the app doesn't crash. I set animation settings to NO and I am still getting the same issue.
Order of events:
Parent View show Modal View A
Modal View A shows Modal View B in Modal View A controller
Parent View dismisses Modal View A in Modal View A controller via delegation
This is where my UI hangs, I can see Modal View B but can't click on it, or do anything
You could use this
[[[self presentingViewController] presentingViewController] dismissModalViewControllerAnimated:YES];
A modal view controller must have a parent view controller in order to display. If you dismiss the parent view controller ("modal view A", in your case), behavior will be unpredictable.
If you're certain that nested modal view controllers are what you really want, you'll need to dismiss them in reverse order; wait until you're done with "B", then dismiss "B", then dismiss "A".
If you don't need the modal presentation style, you would be better off using a UINavigationController to maintain your stack of view controllers.
Update: here is how I would rearrange your order of events. Presented as code for clarity.
[parentView
presentViewController:modalViewControllerA
animated:YES]
[modalViewControllerA
presentViewController:modalViewControllerB
animated:YES]
[modalViewControllerA
dismissModalViewControllerAnimated:YES]
[parentView
dismissModalViewControllerAnimated:YES]
Solved by having my parentViewController act as the delegate. Here is my order:
[parentView presentViewController:modalViewControllerA animated:YES]
[parentView dismissModalViewControllerAnimated:YES]
[parentView presentViewController:modalViewControllerB animated:YES]
//Modal B dismisses himself
In my delegate method, I needed to make sure that I dismissed Modal A before presenting Modal B
For iOS 6+ and - presentViewController:animated:completion:
[[[self presentingViewController] presentingViewController] dismissViewControllerAnimated:YES completion:nil];
in Swift 2.1
you can try
self.presentingViewController?.presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
works for me
View A -> View B -> View C
Apply this code in view C , you will be landing to View A
I have a main view and need to show a modalview1 where a button present a modalview2. Looks the same you needed.
But there is a button in the modalview2 which forwards to the main view.
So the solution is:
Main view presents UINavigationController with modalview1 as rootController. Then modalview1 present modalview2 by "[self.navigationController modalview2 animated:YES];".
When modal2 needs to forward to the main view, just make "[self.parentViewController dismissModalViewControllerAnimated:YES];" and UINavigationController is hidden.
Hope it's clear.
Simple:
Dismiss all views:
[self dismissModalViewController animated:YES];
[self dismissModalViewController animated:YES];
[self dismissModalViewController animated:YES];
[self dismissModalViewController animated:YES];
(one for each added modal view)
then present a new modal view controller
may be after long but.. I am in same problem and this is the only post with some answer.
I am not getting what you mean by setting delegate of a parentViewController to self is not allowed .
what I am doing right now is
[self presentModalViewController:ViewControllerA animated:YES];
[self dismissModalViewControllerAnimated:YES];// inside ViewControllerA
[self presentModalViewController:ViewControllerB animated:YES];
[self dismissModalViewControllerAnimated:YES];// inside ViewControllerB
Problem is after viewControllerA , viewControllerB view is not presenting.
Thanks,
Apple document about dismiss(animated:completion:) method.
In section Discussion, it said:
any intermediate view controllers are simply removed from the stack.
If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack. The top-most view is dismissed using its modal transition style, which may differ from the styles used by other view controllers lower in the stack.
In other words, if the view controller stack like following
Root -> A -> B -> C -> D ... -> Z
D calls dismiss method, all view controllers behide D, ex: (E ... Z), will be removed from the stack.