I have a UIViewController which has a button that performs a modal segue to a UIViewController as a Form Sheet. On that form sheet is a cancel button with an unwind segue back to the original UIViewController. This seems to work perfectly happily and dismisses the form sheet.
As soon as I select the original UIViewController and select the option in XCode to Embed in a Navigation Controller, the unwind segue no longer seems to work and the modal form sheet will no longer cancel.
I'm sure there is a simple explanation, but it is currently evading me, so any thoughts welcomed.
Thanks.
I don't know why you get the behavior you're seeing, I see it too. It happens for both the page sheet and form sheet presentations, but not for full screen. However, the unwind segue is still calling the method you put in the original controller (the one you connected the unwind segue to). So, all you need to do is put a line in that method:
[self dismissViewControllerAnimated:YES completion:nil];
This is already answered, but the above did not give me the full solution, so i thought i would share mine.
For me the unwind method was never called, so i could not do what was described above. Instead i made a simple button with an IBAction and called it. Swift example below:
#IBAction func cancelToRecipeController() {
self.dismissViewControllerAnimated(true, completion: nil)
print("cancel to recipe controller ran")
}
Thanks to #rdelmar above for the method call!
(This was added for ios 9)
self.dismissViewControllerAnimated(true, completion: nil)
"dismiss" didn't work for me but popToRoot works well.
[self.navigationController popToRootViewControllerAnimated:YES];
Related
I've looked up examples on how to reverse segue in xcode and swift with a storyboard but I can't find an example that pertains to this specific situation where I segue into a navigation controller beforehand. Any pointers?
If you use navigation controller, you can use
self.navigationcontroller?.popviewcontroller(animation: true)
Please try this
It is the same as an ordinary unwind segue.
In your source view controller add this action
#IBAction func unwindToMain(segue: UIStoryboardSegue) {}
And from your destination view (which is titled Action) connect your button to the Exit.
Hope this helps :)
I have viewcontroller A and on click of button, i have opened a another viewcontroller with presentation style as Form sheet. In second view controller which is opened have two buttons. Now, when these buttons are clicked, this second view controller should go away and next view controller should open on top of view controller A. But when i am trying below, another view controllers are opening up inside the dialog
i don't know how to unwind this segue and call another scene together.
Nitya, did you try the following piece of code to dismiss current view controller. Use it in the IBAction of the button where you want to dismiss the viewController:-
self.dismissViewControllerAnimated(true, completion: nil)
So you have a root viewcontroller A with a button. If you tap that button, an other viewcontroller (let's name it B) is presented by A as a form sheet. B has two buttons and if you tap one of those buttons, B should be dismissed and after a different viewcontroller (let's say C) shold be presented by A.
Apple don't really recommend this kind of workflow, nevertheless it is possible to implement it. You may shold consider to use navigation controller or master-detail controller instead of this. But if you stick to your original idea here are some possible implementations:
1.
If you are using a storyboard and the button on B triggers an unwind segue to A then you can add this to the end of the unwind seque action:
dispatch_async(dispatch_get_main_queue(), ^{
[self performSegueWithIdentifier:#"segueThatPresentsC" sender:nil];
});
2.
If you present your viewcontrollers programmatically then:
Before you present B from A you can configure a button of B so that ist target is A and and its action is a method defined in A:
- (void) dismissAndPresentC {
[self dismissViewControllerAnimated:YES completion:^{
[self presentViewController:instanceOfC animated:YES completion:nil];
}];
}
This second is maybe a bit smaller hack, but still a confusing concept.
Let me start by saying that I want to do all of this without storyboards. My situation is as follows: I have a login page for the user. On the login page the user can login, or be taken to a register page. When the user registers successfully, they are taken to the main menu. However, if I they click logout from the main menu, dismissing the main menu viewcontroller takes me back to the register page (which makes sense).
The problem is I need to take the user to the login page. However, I cannot present the original login page because I get the error "Warning: Attempt to present on which is already presenting "
Is there some sort of way for me to dismiss 2 view controllers? Or maybe run a line of a code on a view controller if it is presented from a certain view controller?
Thank you!
This is the solution that I used from the main menu and it worked
if(self.presentingViewController == registerPage){
registerPage.dismissViewControllerAnimated(true, completion: nil)
}
self.dismissViewControllerAnimated(true, completion: nil)
If you are using a navigation controller, you can get the viewControllers array property, build up a new array without the viewControllers you want to dismiss and set the property with the new array.
No need to switching to Navigation controllers.
If you are presenting view controller than simply try this:
For Objective-C:
[[[self presentingViewController] presentingViewController] dismissViewControllerAnimated:YES completion:nil];
For Swift:
self.presentingViewController!.presentingViewController!.dismissViewControllerAnimated(true, completion: {})
Hope it will work for you.
I'm working on a storyboard-based iPhone app.
I am successfully using unwind segues to navigate my stack of view controllers.
However, when I present a modal view controller I cannot seem to be able to trigger the unwind segue that I have specified in the storyboard file.
Is this normal or a bug?
Problem solved.
Apparently I've hit some glitch with the storyboard editor.
What I did was to delete the destination (modal) view controller and then re-create it.
Works fine, now.
Bug report filed.
So I have the same problem (more than two years later!). I haven't fixed the underlying issue, but I found that a modal view being presented with a default presentation style will unwind OK, but one that uses a page sheet presentation style simply doesn't work. The unwindToViewX method gets called on the parent view controller that the unwind segue is moving to, though, so I've circumvented the issue with the following code:
if (self.presentedViewController) {
[self dismissViewControllerAnimated:YES completion:NULL];
}
This saves me from setting up a delegate system as the unwind action is doing all the heavy lifting, but also avoids an issue where perhaps the unwind action might work one day, because in that case self.presentedViewController should return NO because the unwind action worked correctly and we won't end up dismissing two view controllers by accident.
I hope this helps others in the same boat, but I'd also like to hear if anyone else has better solutions.
On my app's start up, it programmatically shows a LoginViewController using a segue. The view controller is presented modally with transition set to cross dissolve. Upon successful authentication, I want to dismiss the login view by programmatically triggering an unwind segue. So I added this to my header file:
- (IBAction)unwindSegue:(UIStoryboardSegue *)segue;
now in IB I'm able to control-drag from the "File's Owner" LoginViewController to the Exit button and choose unwindSegue:. This creates a manual segue, it shows up in the Connections inspectors for the File's Owner and the Exit button correctly. I then click on the newly created Unwind segue from the scene in IB and then give it a name. If I click on the "go to" button for the unwind segue action it takes me to the declaration mentioned above.
So far so good, I then trigger this unwind segue upon successful authentication in my GCD block:
....
dispatch_async(dispatch_get_main_queue(), ^
{
[self performSegueWithIdentifier:#"UnwindSegueIdentifier" sender:self];
[self.spinner removeFromSuperview];
self.spinner = nil;
});
.....and nothing happens when it runs. The spinner does get removed correctly, but there's no sign of that unwind segue executing.
A break point in the implementation of unwindSegue: never gets hit. There are no errors thrown. Nothing gets written to the console. The identifier is correct, I triple checked (otherwise it will fail anyway).
I looked at the answers here, here and here but I don't seem to have missed anything.
What I did notice though, is that Xcode thinks unwindSegue: is not linked:
I'm unable to drag from the little empty circle in front of unwindSegue: and link it to the Exit button.
Any help will be appreciated.
If you are using a modal segue to go to your login view, all you need to go back is to call
[self dismissViewControllerAnimated:YES completion:nil];
More precisely, you should call it at the presenting controller (your first controller), but it will be forwarded if you call at at the presented controller. You can use the completion block do any required clean up. There is no need to use GCD.
EDIT
To answer the additional comment: I'm not really sure from your description, but it seems you've implemented the unwind action at the presented controller instead at the presenting controller. Unwind segues are to allow to do something at the caller (e.g., setting data) without an additional protocol.
Quoting text from Apple's Technical Note on Unwind Segue:
To add an unwind segue that will only be triggered programmatically, control+drag from the scene's view controller icon to its exit icon, then select an unwind action for the new segue from the popup menu.
Link to the Technical Note