Dismissing both UINavigation views and Modal views at once programmatically
If you want, in iOS 6.0 (and later) projects you can use an unwind segue. For example, you can:
In your top level view controller (the one you want to unwind to, not the controller you're going to unwind from), write an unwind segue method, in this case called
unwindToTopLevel
(personally, I find it useful if the segue bears some indication as to what the destination of the segue is, for reasons that will become apparent when we get to step 3, below):- (IBAction)unwindToTopLevel:(UIStoryboardSegue *)segue
{
NSLog(@"%s", __FUNCTION__);
}In the Interface Builder scene from which you will initiate the unwind, control ⌘-drag from the view controller icon to the exit icon to create the unwind segue:
Generally you'd define the segue from a button to the exit outlet (and you're done), but if you want to invoke the segue programmatically, you might want to create it between the controller and the unwind outlet, like shown above.
You'll get a little pop up that includes the name of your unwind segues (from the presenting controllers ... it's like magic):
If you're going to invoke that segue programmatically, you have to select that unwind segue in the document outline on the left side of the IB window and once you've done that, you can give the unwind segue a storyboard id:
I generally use the name of the the unwind segue for the storyboard id, but you can use whatever you want.
Now, having done that, your alert view can invoke the segue:
- (IBAction)didTouchUpInsideButton:(id)sender
{
[[[UIAlertView alloc] initWithTitle:nil message:@"go home" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil] show];
}
#pragma mark - UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != [alertView cancelButtonIndex])
{
[self performSegueWithIdentifier:@"unwindToTopLevel" sender:self];
}
}
Dismissing both UINavigation views and Modal views at once programmatically
If you want, in iOS 6.0 (and later) projects you can use an unwind segue. For example, you can:
In your top level view controller (the one you want to unwind to, not the controller you're going to unwind from), write an unwind segue method, in this case called
unwindToTopLevel
(personally, I find it useful if the segue bears some indication as to what the destination of the segue is, for reasons that will become apparent when we get to step 3, below):- (IBAction)unwindToTopLevel:(UIStoryboardSegue *)segue
{
NSLog(@"%s", __FUNCTION__);
}In the Interface Builder scene from which you will initiate the unwind, control ⌘-drag from the view controller icon to the exit icon to create the unwind segue:
Generally you'd define the segue from a button to the exit outlet (and you're done), but if you want to invoke the segue programmatically, you might want to create it between the controller and the unwind outlet, like shown above.
You'll get a little pop up that includes the name of your unwind segues (from the presenting controllers ... it's like magic):
If you're going to invoke that segue programmatically, you have to select that unwind segue in the document outline on the left side of the IB window and once you've done that, you can give the unwind segue a storyboard id:
I generally use the name of the the unwind segue for the storyboard id, but you can use whatever you want.
Now, having done that, your alert view can invoke the segue:
- (IBAction)didTouchUpInsideButton:(id)sender
{
[[[UIAlertView alloc] initWithTitle:nil message:@"go home" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil] show];
}
#pragma mark - UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != [alertView cancelButtonIndex])
{
[self performSegueWithIdentifier:@"unwindToTopLevel" sender:self];
}
}
Dismissing multiple modal views
I don't think that your way is wrong. It is what Apple documentation recommends:
If you present several modal view controllers in succession, and thus build a stack of modal 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.
How to correctly dismiss a UINavigationController that's presented as a modal?
Your controller hierarchy looks like this:
UITabViewController
|
| presents
|
UINavigationController
|
| contains view controllers
|
[root, MessagesViewController]
Now, if you are inside MessagesViewController
, then its navigationController
is the one that is being presented and that's the one you should be dismissing but calling dismiss
on MessagesViewController
should work too.
However, the problem is that dismissing the navigation controller won't remove its view controllers. It seems you are holding to your navigation controller (since you are presenting it using self.navController
) so the state will become
UITabViewController
|
| self.navController holds a reference to
|
UINavigationController
|
| contains view controllers
|
[root, MessagesViewController]
To properly destroy MessagesViewController
you will have to either let go of the navController
or you will have to pop to root (thus removing MessagesViewController
from view hierarchy).
The typical solution would be not to save a reference to navController
at all. You could always create a new UINavigationController
when presenting.
Another solution is using a delegate - instead of dismissing from inside MessagesViewController
, let it call back to the presenter, which would call
self.navController.dismiss(animated: true) {
self.navController = nil
}
Displaying modal views programmatically
You can try below code
I assume that you are using storyboard.
UIStoryboard *board = [UIStoryboard storyboardWithName:@"name" bundle:nil];
viewController *controller = [board instantiateViewControllerWithIdentifier:@"Identifier"]; // Identifier is define in storyboard
[self presentViewController:controller animated:YES completion:nil];
Please check out this link if you are still facing the problem.
Hope this helps you.
single function to dismiss all open view controllers
You can call :
self.view.window!.rootViewController?.dismiss(animated: false, completion: nil)
Should dismiss all view controllers above the root view controller.
Related Topics
Uitableviewcelldeleteconfirmationcontrol Issue
Ios:Retrieve Rectangle Shaped Image from the Background Image
Searchdisplaycontroller Deprecated in iOS 8
Is Possible to Simulate Touch Event Using an External Keyboard on iOS Jailbroken
How to Do a Native "Pulse Effect" Animation on a Uibutton - iOS
What Is a Provisioning Profile Used for When Developing iPhone Applications
Connect Outlet of a Cell Prototype in a Storyboard
How to Generate a Barcode from a String in Swift
Uniquely Identifying an iOS User
How to Get Managedobjectcontext for Viewcontroller Other Than Getting It from Appdelegate
How to Convert an Uiimage to Grayscale in Swift Using Cifilter
Uitableview Auto Resizing Row Constraint Breaking Mysteriously on iPhone 6Plus
Presenting Uiviewcontroller from Skscene
Running Xcodebuild from a Forked Terminal
What Does Get-Task-Allow Do in Xcode
Save and Retrieve Value via Keychain
How to Display the Standard Checkmark on a Uicollectionviewcell