dismissViewController clear the screen but doesn't dismiss - ios

I have 2 screens:
The first call the second with the following code:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:kDetailSegue]) {
[NSThread detachNewThreadSelector:#selector(loadingThread) toTarget:self withObject:nil];
TagDetailControllerViewController* detailController = segue.destinationViewController;
detailController.location = self.recentLocation;
}
}
The kDetailSegue is a present modally - presentation default - transition: default
In second ViewController, I'm trying to dismiss the screen:
[self.navigationController dismissViewControllerAnimated:YES completion:nil];

It is not clear what you want to dismiss in your second view controller, so I will try to present the most likely scenarios:
If you want to dismiss the view controller presented modally (TagDetailControllerViewController), you need to dismiss it modally too.
This can be achieved by calling in your TagDetailControllerViewController itself:
[self dismissViewControllerAnimated:YES completion:nil];
Which works because, according to Apple's documentation:
If you call this method on the presented view controller itself, it automatically forwards the message to the presenting view controller.
Also, if you want to dismiss it directly from the view controller you used to present it, you can do it as follows:
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
Finally, if what you want is to dismiss a view that was pushed in your UINavigationController, then you can just pop it from the stack:
[self.navigationController popViewControllerAnimated:YES];
As you can see, the way a view is dismissed really depends on the way it was presented.

try this
[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:NULL];

Related

Dismissing previously presented modal view controller before currently visible one

I have 2 UIViewController's presented with [self presentViewController:viewController animated:YES completion:nil];, I want to dismiss the first one of them, without animation (It's not visible to the user anyway) and when the second one (currently visible) will be dismissed, the user will see the parent view controller who present them both.
- Parent
- First -> Dismiss first without animation
- Second -> Dismiss second with animation
How can I do that?
With your current view controller hierarchy if first view controller will be dismissed it will dismiss second view controller automatically. If you don't want that behaviour than make parent present second view controller. You can do that from first view controller by using [self.presentingViewController presentViewController:secondViewController animated:YES completion:nil]
Why do you want to do this?
You should do it like this for cleaner view hierarchy and better user experience:
Present first view controller :
[self presentViewController:viewController1 animated:YES completion:nil];
Dismiss first & present second view controller :
__weak MyViewController *aBlockSelf = self;
[self dismissViewControllerAnimated:YES completion:^{
[aBlockSelf presentViewController:viewController2 animated:YES completion:nil];
}];

iOS back to root ViewController in the modal and navigation uiviewcontroller

I have a structure about navigation and many page have modal (popup) on the uiviewcontroller(UINavigationController).
When I disconnect the bluetooth, I need back to the root the viewcontroller.
So I set the dismiss and popToRoot in the disconnect method
-(void) disconnect
{
....
[appDelegate.window.rootViewController dismissViewControllerAnimated:NO completion:nil];
NSLog(#"appDelegate.window.rootViewController:%#",appDelegate.window.rootViewController.class);
// show log appDelegate.window.rootViewController:UINavigationController
[appDelegate.window.rootViewController.navigationController popToRootViewControllerAnimated:YES];
....
}
But when I run the program and disconnect bluetooth,
In the case 1: modal the viewcontroller showing,
It will dismiss the modal viewcontroller, the dismiss was correct.
But there are not back to the root navigation controller after dismiss modal viewcontroller.
In the case2: just in the uinavigation controller page.
when I disconnect the bluetooth, there are not back to the root navigation controller.
How can I back to the navigation root page?where are my fails?
thank you very much.
// ------ answer -------
change code to
[appDelegate.window.rootViewController dismissViewControllerAnimated:NO completion:nil];
[self performSelector:#selector(gotoRoot) withObject:nil afterDelay:0.50];
- (void) gotoRoot {
UINavigationController *myNavCon = (UINavigationController*)appDelegate.window.rootViewController;
[myNavCon popToRootViewControllerAnimated:YES];
}
From the class you presented your modal view call dismiss of modal and then perform selector after some delay and then do the here is the sample code
- (void) dismissAndGoToRoot {
[self dismissViewControllerAnimated:YES completion:nil];
[self performSelector:#selector(gotoRoot) withObject:nil afterDelay:0.50];
}
- (void)gotoRoot {
[self.navigationController popToRootViewControllerAnimated:NO];
}
From apple developer documentation about dismissViewControllerAnimated:completion:
completion: The block to execute after the view controller is dismissed. This block has no return value and takes no parameters. You may specify nil for this parameter.
So I think this is better solution
[self dismissViewControllerAnimated:YES completion:^(){
[self.navigationController popToRootViewControllerAnimated:NO];
}];
Using completion block is better than afterDelay. How do you choose the good delay ? What happens if too short ? If too long, execution code waits for nothing ...

Dissmis a modal viewcontroller on a Storyboard

I'm developing an iPhone application with latest SDK.
I don't know how to dismiss a ViewController. I've added a back button and this is what I do:
- (IBAction)backButtonClicked:(id)sender
{
[self.navigationController dismissModalViewControllerAnimated:YES];
}
I have also tried:
[self.navigationController popViewControllerAnimated:YES];
But either works. I've added a breakpoint and it stops on it.
And I use a Modal segue to navigate to this ViewController.
How can I dismiss this View Controller programmatically?
Try [self dismissViewControllerAnimated:YES completion:nil];
- (IBAction)backButtonClicked:(id)sender
{
[self.presentingViewController dismissViewControllerAnimated:YES
completion:nil];
}
Is the VC being modally displayed an instance of your own view controller subclass, or did you wrap that inside a UINavigationController? If the former, try
[self dismissModalViewControllerAnimated:YES];
[self.presentingViewController dismiss...] will also work, but only for iOS 5+
create a custom segue,then button action choose the custom segue
http://jeffreysambells.com/2014/02/19/dismissing-a-modal-view-using-a-storyboard-segue

Dismissing 2 ViewController consecutively

I try 2 ways to dismissed 2 viewcontrollers consecutively but only one of them got dismissed not the second one
method1
-(void) LoginDone:(NSNotification *)notif
{
[self dismissViewControllerAnimated:YES completion:NULL]; //previous viewcontroller
[self dismissViewControllerAnimated:YES completion:NULL]; //current viewcontroller
}
method2
-(void) LoginDone:(NSNotification *)notif
{
[self dismissViewControllerAnimated:YES completion:NULL];
[[NSNotificationCenter defaultCenter] postNotificationName:#"LoginDone2" object:nil];
}
-(void) LoginDone2:(NSNotification *)notif
{
[self dismissViewControllerAnimated:YES completion:NULL];
}
I need to find out a way to dismiss both the previous viewcontroller and current viewcontroller consecutively.
This is now an old question, but it seems to be exactly the problem I am having presently.
Here what I did:
[self.presentingViewController.presentingViewController
dismissViewControllerAnimated:YES completion:nil];
And it works for me. I hope it can be useful to someone.
By calling
[self dismissViewControllerAnimated:YES completion:NULL];
you are telling self to dismiss the view it presented. Telling twice the same self object to dismiss the view it presented, will not change the result. In other words self cannot represent the "current view" and the "previous view" at the same time as per your comment to the code. self is just a single controller representing a single view, either the current or the previous one.
To fix this, you should send the dismissViewControllerAnimated to self (that presented the top-most view, I assume) and to the other view controller object that presented the previous view.
In other words, I would expect something like this:
-(void) LoginDone:(NSNotification *)notif
{
[self dismissViewControllerAnimated:YES completion:NULL];
[self.previousController dismissViewControllerAnimated:YES completion:NULL];
}
Actually, you could send just one message to the second view controller and both views would be dismissed (source):
If you present several view controllers in succession, and thus build 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.
I know this is an old question but maybe somebody will look for solution on this issue so here it is:
-(void) closeModalViews
{
[previousVC dismissViewControllerAnimated:YES completion:^(void) {
[self dismissViewControllerAnimated:YES];
}];
}
I like JPetric's idea, but first you must dismiss the current view controller's view and only then can you dismiss the presenting view controller's view.
[self dismissViewControllerAnimated:NO completion:^(void) {
[self.presentingViewController dismissViewControllerAnimated:NO completion:nil];
}];
As far as I could understand you are trying something like below:
There are 2 view controllers.
You want both of them to be vanished.
Another controller comes in.
But the fact is only one controller is displayed, why you would need to dismiss 2 then?
You can use self.view.hidden=true; on the jumped viewcontrollers while animating back to the first viewcontroller. Using [self.presentingViewController dismiss...] is not working for me without hiding.

Dismiss modal view then perform segue to open a second modal view

I have a HomeController that allows a user to log in and register. If the user clicks login, I open a modal view using a segue.
Inside the modal view there is a button that says register. The desired action is to close the login modal view and then open the registration modal view using performSegueWithIdentifier:
- (void)loginControllerDidRegister:(LoginController *)controller sender:(id)sender
{
NSLog(#"loginControllerDidRegister");
[self dismissViewControllerAnimated:YES completion:nil];
[self performSegueWithIdentifier:#"RegistrationSegue" sender:sender];
}
This correctly dismisses the modal view, then it calls performSegueWithIdentifier:, where I have logging code that shows it is being called just as if I had pressed the register button.
I think the animation of the login modal view disappearing may be interfering with the display of the second modal view. Any ideas on what can be done to fix this?
well you need to have your "second modal" vc initiated. this is what the "prepareForSegue:" method does. also you need to override the "perform:" method. this is going to be a bit more complicated than you think. if is helps here is a breakdown of how a segue works...
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender;
gets called and passes in "segue". behind the scenes
- (id)initWithIdentifier:(NSString *)identifier source:(UIViewController *)source destination:(UIViewController *)source;
gets called, and this is where "segue" is created.
the "segue" object has properties of
(NSString *)identifier
(UIViewController *)sourceViewController
(UIViewController *)destinationViewController
with out these a segue can not be performed. these are akin to manually allocating your view controller
SomeViewController *secondView = [SomeViewController alloc] initwithNibName:#"SomeViewController" bundle:nil];
then
[[segue destinationViewController] setModalTransitionStyle:UIModalTransitionStyle(...)];
which is...
secondView.modalTransitionStyle = UIModalTransitionStyle(...);
the (...) would be the "segue" transition selected in the storyboard.
lastly
[[segue sourceViewController] presentModalViewController:destinationViewController animated:YES];
which is just
[self presentModelViewController:secondView animated:YES];
is what makes it all happen. you will basically have to tweak with those under the hood goings on to get what you want working, but it is do-able.
you must put the performSegue of your second modal view controller in the completion block of the dismissViewControllerAnimated call. UINavigationController can't handle the presentation when it is still presenting the other modal view controller.
If someone has the same question.
- (void)loginControllerDidRegister:(LoginController *)controller sender:(id)sender
{
NSLog(#"loginControllerDidRegister");
[self dismissViewControllerAnimated:YES completion:^{
[self performSegueWithIdentifier:#"RegistrationSegue" sender:sender];
}];
}

Resources