Dismissing View Controller in Modally Segue - ios

I am creating an app that opens with ViewController1, then a button opens another view contoller (ViewController2) with a modally segue. Then ViewController2 has a button that opens another view controller (ViewController3) using another modally segue. Both 2 and 3 view contollers have a dismiss button that dismisses the view controller.
The problem is that whenever ViewController3 uses the dismiss button, it dismisses to ViewController 2 when I want it to dismiss to ViewController1. I've tried using the dismiss action to dismiss ViewController2 one the button is pressed, but then the segue doesn't get committed.
This may be confusing so please ask questions if you need help understanding. Thanks so much in advace!
(I am using Swift 3 and Xcode 8)

Two options off the top of my head:
1. Use NotificationCenter and Send a dismiss notification that ViewController2 is listening for
2. Set a parentViewController reference on ViewController3, and then call dismiss on the parent after dismissing itself.

This happen because all the 3 viewcontroller are in stack,whenever u dismiss the viewcontroller in top it moves to the one below it.
To navigate to viewcontroller1 use:-
if let viewcontroller1 = navigationController?.viewControllers[0]{
_ = navigationController?.popToViewController(viewcontroller1, animated: true)
}

it's simple!
//*** in ViewController2
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.onCloseViewController2), name: NSNotification.Name(rawValue: "closeViewController2"), object: nil)
func onCloseViewController2() {
//this function is called from notification (sent by vc3)
self.navigationController?.dismiss(animated: true, completion: nil);
}
#IBAction func closeView2FromButton() {
//Directly close modal
self.onCloseViewController2();
}
//*** in ViewController3 (tap button)
#IBAction func closeView3FromButton() {
//dismiss vc3 and send a notification to vc2
self.navigationController?.dismiss(animated: true, completion: {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "closeViewController2"), object: nil);
});
}
Remember to later remove the observers when you do not need them in your code ;)

Related

How to get back from modal to main view controller

I'm totally newbie level with swift and having a question. so, I created a navigation controller for my modal and having my modal opened up from my first view controller with segue (Button2). The question is, how to get back to my first view controller from Modal View
You can use the dismiss method to dismiss a specific ViewController.
The question is how you want to dismiss the ViewController presented modally? With a button? Tap anywhere in the View? Tap on a little cross button?
For example if you have an UIButton to dismiss:
#IBAction func didTapClose(_ sender: UIButton) {
dismiss(animated: true, completion: nil)
}
If the segue is "present modally", you can dismiss the view controller through this line :
dismiss(animated: true, completion: nil);
Else If the segue is "show", you can dismiss the view controller through this line :
navigationController?.popViewController(animated: true);
In this case, be sure that you embedded your ViewController to a navigationController in your storyboard. If your ViewController is not embedded to a navigationController and you have used show segue, you should use dismiss(animated: true, completion: nil) to return to previous page.
Also there is other ways to return to previous pages (e.g., unwind segue)
Good luck.

How to dismiss a view when leaving it with tab bar controller

I use a tab bar controller to go from VC1 to VC2. Doing so, VC1 stays in memory. I manage data with VC2 and when I go back to VC1 (with tab bar controller), I reload VC1 with a function in viewWillAppearit works fine, but the previous version of VC1 is still visible during animation reloaded.
I have to dismiss the VC1 (from the memory) before the animation or reload process begins.
I have tried, in viewWillAppear, and viewDidDisappear of VC1 these commands without success.
self.dismiss(animated: true, completion: nil)
self.presentedViewController?.dismiss(animated: true, completion: nil)
My guess is that the best approach is to dismiss VC1 when moving to VC2, but didn't find the way yet.
Thanks for your help.
My suggestion, use NotificationCenter to add observer in VC1 and trigger from VC2 if some event happen.
Adding observer.
NotificationCenter.default.addObserver(forName: Notification.Name(rawValue: "updateVC1"),
object:nil, queue:nil) {
notification in
// do something
}
Trigger the observer from VC2
NotificationCenter.default.post(name: Notification.Name(rawValue: "updateVC1"), object: nil)

dismiss two controllers Swift

I have this situation :
I have a first view controller , when tap on button in it I open in modal mode another view controller , in this view controller when I tap another button I open in modal view another view controller and in it there is a button and when I tap on it I want to go to first view controller without re-initialize it.
How do I do it?
This is the perfect situation for an unwind segue.
Put this in your first viewController (the one you want to return to):
#IBAction func backFromVC3(_ segue: UIStoryboardSegue) {
print("We are back in VC1!")
}
Then in the Storyboard in your 3rd viewController, control-drag from your button to the exit icon at the top of the viewController and choose backFromVC3 from the pop-up.
Now, when the user presses the button in VC3, both VC3 and VC2 will be dismissed and you will return to VC1.
If you are not using Storyboards, you can dismiss the viewControllers with code. Here is code for a button's handler to dismiss two levels of viewController:
func doDismiss(_ sender: UIButton) {
// Use presentingViewController twice to go back two levels and call
// dismissViewController to dismiss both viewControllers.
self.presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil)
}
Thanks all for reply and edited my question :)
I found 2 line code to resolved my problem:
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.window!.rootViewController?.dismissViewControllerAnimated(true, completion: nil).
And that work well.
Thanks very much

Go back to previous view controller doesn't work

My first view controller has a button, which triggers the #IBAction goTo2ndVc() which presents a second ViewController:
class FirstVC: UIViewController {
...
#IBAction func goTo2ndVc() {
let secondVc = SecondVC(label: "I am second vc.")
self.presentViewController(secondVc, animated: true, completion: nil)
}
When the button is pressed, the 2nd view controller is shown on screen. No problem.
In 2nd view controller, there is also a button which is used to go back to 1st view controller:
class SecondVC: UIViewController {
...
#IBAction func backToFirst(sender: AnyObject) {
print("go back ...")
self.navigationController?.popViewControllerAnimated(true)
}
}
I looked on internet, people suggest to use navigationController?.popViewControllerAnimated(true) to go back to previous controller. But when I press the go back button I can see the print message "go back ..." but the app doesn't go back to 1st view controller. WHY?
#IBAction func backToFirst(sender: AnyObject) {
print("go back ...")
self.dismissViewControllerAnimated(true, completion: nil)
}
In Swift 3
self.dismiss(animated: true, completion: nil)
you should not use navigation controller, because you didn't use it when you were adding the second view controller. that's why simply call dismissViewControllerAnimated method.
You have to use UINavigationController and its pop methods only when you add your view controllers via pushViewController method.
Familiarize yourself with the concept of navigation controller here: https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/NavigationControllers.html
there
the issue is very simple..
self.presentViewController(secondVc, animated: true, completion: nil)
the code will present second view, you are not pushing it.
self.navigationController?.popViewControllerAnimated(true)
the popViewController will pop back to the previous view controller from where it is been pushed.
So, there are two ways you can achieve what you want
1)If you want to present viewController then you have to dismiss the view controller to show previous view controller with
self.dismissViewControllerAnimated(true, completion: nil)
2)If you want to use PopToVewcontroller, then you have to push you second view controller instead of presenting it with
self.navigatioVonroller?.pushViewController(secondVc, animated: true)
If you want to return to the previous view controller, you can simply add:
[self dismissViewControllerAnimated:YES completion:nil];
to the button action method.
If this is added on the nav view controller present on every screen, I see no reason why it shouldn't work as it would always dismiss the most recently presented view.

How to properly dismiss the presented ViewController and go back to the parent ViewController?

I'm facing an issue that I will describe and have found some similar questions, but I don't believe pertains to my issue.
I have a UITabBarController with 2 tabs for VC1 and VC2. VC1 segues to VC4. VC2 segues to VC3 and VC3 segues to VC4. VC4 contains an MPMoviePlayerViewController instance, as depicted below:
- - - - - -> VC1 \
TAB BAR VC / - - -> VC4
\ /
-> VC2 -> VC3 -> /
I have a Notification that listens to when the Video finishes, and dismiss VC4, and go back to whichever parent VC presented VC4, i.e. if VC1 presented VC4, then upon dismissal of VC4, should go back to VC1. Likewise, if VC3 presented VC4, then upon dismissal of VC4, should go back to VC3.
In VC4:
override func viewDidLoad()
{
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: "moviePlayerPlayBackDidFinish:",
name: MPMoviePlayerPlaybackDidFinishNotification,
object: player?.moviePlayer)
}
func moviePlayerPlayBackDidFinish(notification: NSNotification)
{
NSNotificationCenter.defaultCenter().removeObserver(
self,
name: MPMoviePlayerPlaybackDidFinishNotification,
object: notification.object
)
player!.view.removeFromSuperview()
self.presentedViewController?.dismissViewControllerAnimated(true, completion: nil)
}
I don't think I'm using the code properly because self.presentedViewController?.dismissViewControllerAnimated(true, completion: nil) stays at VC4.
I found some similar questions:
How to dismiss the current ViewController and go to another View in Swift
How to dismiss VIewController iOS Swift
modal View controllers - how to display and dismiss
However, the sequence segues are different, therefore I can't follow the suggestions.
How can I achieve this? Thanks
UPDATE:
The following code in moviePlayerPlayBackDidFinish properly dismisses VC4 and back to parent VC1 if going from VC1 -> VC4:
self.dismissViewControllerAnimated(true, completion: nil);
However, VC4 does not dismiss when going from VC3 -> VC4.
Finally solved my issue by adding the additional code in moviePlayerPlayBackDidFinish:
self.navigationController?.popViewControllerAnimated(true)
After much research, I found the solution from here: dismissViewControllerAnimated() does not dismiss view controller

Resources