Here's my set-up:
Nav Controller: ViewcontrollerA -> ViewControllerB
ViewcontrollerB displays a imagePickerController, setting itself as Delegate
If the user hits CANCEL from the UIImagePicker, I was to dismiss ViewControllerB completely, popping the user back to ViewControllerA.
In:
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
I have called:
[self dismissViewControllerAnimated:YES completion:nil];
and
[[self parentViewController] dismissViewControllerAnimated:YES completion:nil];
and
[[[self parentViewController] parentViewController] dismissViewControllerAnimated:YES completion:nil];
No luck, ViewControllerB still hangs around.
How to I completely dismiss B programmatically from itself?
Is ViewControllerA presenting ViewControllerB or is ViewControllerB being pushed via your navigation controller? It sounds like it's being pushed. In this case I would try
[[self navigationController] popViewControllerAnimated:YES];
Edit for clarity:
You do want to dismiss the image picker the way you already are. You want to use popViewControllerAnimated to get rid of ViewControllerB.
The presenting view controller is responsible for dismissing the view
controller it presented. If you call this method on the presented view
controller itself, it automatically forwards the message to the
presenting view controller.
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
Related
My storyboard is using a UINavigationController(VC0), I segue using a UIPopover to load a new UIViewController (VC1). From this new UIViewController, I am popping to a new UIViewController (VC2). When I attempt to close this newest popover, I am being quit back to the UINavigationController.
The code that I'm using in VC0 to show the VC1 as popover, VC1 to VC2 is the same code (different identifier though):
[self performSegueWithIdentifier:#"titlePopover" sender:self];
The code that I'm using in VC2 to dismiss the popover is:
UIViewController *vc = [self presentingViewController];
[self dismissViewControllerAnimated:YES completion:^{
[[vc presentingViewController] dismissViewControllerAnimated:YES completion:nil];
}];
What it does is dismisses VC2, shows VC1 for a split second, then dismisses VC1 and goes back to the VC0. I want to be able to dismiss VC2 only, so that I'm on VC1
If you performing sugue modally, use code navigate back:
[self dismissViewControllerAnimated:YES completion:nil];
If performing push segue, use code to navigate back:
[self.navigationController popViewControllerAnimated:YES];
I have just started working on ios.
I created a Modalviewcontroller (VC1) and presented another modalViewcontroller (VC2).
There is a button (dismiss) on VC2 which will have to dismiss both viewcontrollers.
The way i know is call :-
[self dismissViewControllerAnimated:YES completion:nil];
in VC2
then call the same in VC1
So i created a delegate which tells me if dismiss is clicked in VC2.
so when dismiss is clicked:-
i call
[self dismissViewControllerAnimated:YES completion:nil];
in VC2
then that delegate method takes me to VC1
where I again call
[self dismissViewControllerAnimated:YES completion:nil];
This method was perfectly working till i was using the app in ios9
when i shifted to ios7 i started getting the warning and VC1 was not getting dismissed.
Please let me know why is this happening.
So the part which works for me as told in comments.
[self.presentedViewController dismissViewControllerAnimated:YES completion:^{
[self dismissViewControllerAnimated:YES completion:nil];
}];
So, error tells you exactly what happened. You trying to dismiss VC1, while your VC2 dismissing. By putting dismissViewControllerAnimated into delegate method does not guarantee that VC1 will be dismissed before, instead of that you should call your [self dismissViewControllerAnimated:YES completion:nil]; in completion block after first dismiss, so your code will look like that:
[self dismissViewControllerAnimated:YES
completion:^{
[self dismissViewControllerAnimated:YES completion:nil];
}];
I have two viewcontrollers. Here is the second one:
UIViewController *modal = [[ModalViewController alloc]init];
[self presentViewController:modal animated:YES completion:nil];
Second modal window:
[self dismissViewControllerAnimated:YES completion:nil];
How do I pass parameters from a modal view controller?
If I understand you correctly, you would like to make / tell the presenting controller to dismiss the modal view controller from the modal view controller?
I gather that being the reason why you thought of passing self as "parameter" to the modal view controller, so that it could reference it and make it dismiss the ModalViewController through the use of [self dismissViewControllerAnimated:YES completion:nil]; as you mentioned?
If so, you could make use of protocol:
In your modal view controller's header file (.h), declare:
#protocol ModalViewControllerProtocol
#require
- (void)dismiss;
#end
#interface ModalViewController
In your presented controller, which is ModalViewController in your case, declare the following in .h:
#property(assign, nonatomic) id<ModalViewControllerProtocol>myDelegate;
and make your presenting controller so that it adopts to the protocol:
#interface presentingViewController <ModalViewControllerProtocol>
And:
ModalViewController *modal = [[ModalViewController alloc] init];
modal.myDelegate = self;
[self presentViewController:modal animated:YES completion:nil];
When your modal view controller is presented and you would like to tell your presenting controller to dismiss it, you could do:
[self.myDelegate dismiss];
And finally implement the dismiss method in your presenting view controller:
- (void)dismiss
{
[self dismissViewControllerAnimated:YES completion:nil];
}
One could also forget about all of the aforementioned and simply call the following in the presented view controller (which, in your case, the ModalViewController):
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
But there are cases that self.presentingViewController is not returning the same controller that presented the modal view controller. Hence, using the protocol method would assure that we would like the same presenting view controller to dismiss the presented controller.
I have a navigation controller A on which i push the view controller B. From B i present modally the view controller C. I need to dismiss C and pop B at the same time. I would like to that in sequence, keeping the dismiss animation first and then the pop animation from B to A. I tried without success this code:
[self dismissViewControllerAnimated:YES completion:^{
[self.presentingViewController.navigationController popViewControllerAnimated:YES];
}];
Any suggestion on how can i achieve this?
If you are writing in C viewcontoller then :
UIViewController *pvc = self.presentingViewController;
UINavigationController *navController = [pvc isKindOfClass:[UINavigationController class]] ? (UINavigationController *)pvc : pvc.navigationController;
[self dismissViewControllerAnimated:YES completion:^{
[navController popViewControllerAnimated:YES];
}];
or if in B view controller
[self.presentedViewController dismissViewControllerAnimated:YES completion:^{
[self.navigationController popViewControllerAnimated:YES];
}];
I had tried popping two times in succession before but not dismissing one and popping another one. You can try what I did and see if it works for you.
In Subview B:
- (void)subViewCController:(SubViewCController *)controller didSelectID:(NSNumber *)theID
{
// do something with theID...
// for my case, I popped
// [self.navigationController popViewControllerAnimated:YES];
// for your case
[self dismissViewControllerAnimated:YES completion:nil];
// Somehow, adding a small delay works for me and the animation is just nice
[self performSelector:#selector(backToSubViewA) withObject:nil afterDelay:0.6];
}
- (void)backToSubViewA
{
[self.navigationController popViewControllerAnimated:YES];
}
Are you using storyboards and segues? If so, you can use unwind segue:
In your first view controller (the one you want to jump back to, not the one you're returning from), create an unwind segue action:
- (IBAction)gotoMainMenu:(UIStoryboardSegue *)segue
{
// if you need to do anything when you return to the main menu, do it here
}
Then in storyboard, you can create a segue from the "dismiss" button to the exit outlet icon () in the bar above the scene, and you'll see main menu listed there.
I am loading a ViewController from a Storyboard like this:
SSContentViewController* contentViewController =
[[UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil]
instantiateViewControllerWithIdentifier:#"settingsViewController"];
and add it to my ViewController Array:
[self.viewControllers addObject:contentViewController];
inside the SettingsViewController I have a segue with presents a modal view controller. If I perform this segue I get a "Presenting view controllers on detached view controllers is discouraged"-Warning in the console output.
But there is nothing wrong with it. Everything is working as expected. Is it safe to ignore this warning?
EDIT:
The problem is that the ViewController on which I perform the segue is added to my RootViewController with:
[rootVC.view addSubview:viewController.view];
So I know that it is detached. But even with that warning things are working as they should and do not produce visual errors, etc...
you should actually use presentViewcontroller and dismissviewcontroller to avoid this.
Instead of adding use:
[self.view.window.rootViewController presentViewController:contentViewController animated:YES completion:nil];
And from model view use below to dismiss:
[self dismissViewControllerAnimated:YES completion:nil];
Edit 01:
for frame rate drop try below:
[picker dismissViewControllerAnimated: YES completion:^{
[self performSelector:#selector(reinit) withObject:nil afterDelay:2];
}];