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
Related
I'm having some trouble going from my login VC which is a collectionVC to my main vc which is a navigation controller. No matter what type of segue I choose, i get this gap at the top where you can see the previous login VC, with the possibility to drag from the top of the current navigationVC to dismiss it. I've tried using all the different segues but they all show up like this for some reason. My loginVC has a login button, and changes to the navigation VC with the following code:
// Login user
func loginUser() {
Auth.auth().signIn(withEmail: emailTxtFld.text!, password: PasswrdTxtFld.text!) { (user, error) in
if error != nil {
print(error!)
} else {
print("Login succesfull!")
self.performSegue(withIdentifier: "goToMain", sender: self)
}
}
}
#IBAction func loginBtnTapped(_ sender: Any) {
loginUser()
}
I've connected the loginVC to the main VC with a segue, not the login button itself. The first slide of the navigation VC is a collectionview, the second is blank.
This is not a problem of segue, it is a problem with the ModalPresentationStyle of the presented view controller that, from iOS 13, defaults to automatic.
This means that (most of the) view controllers will be presented in this fashion.
You just need to set this modal presentation style to fullscreen in one of this points:
when you instantiate the view controller
when you prepare for segue
or in the viewDidLoad of the viewController itself
in storyboard segue https://stackoverflow.com/a/56530134/8517882
in storyboard view controller https://stackoverflow.com/a/57546875/8517882
Thank you Enricoza for explaining this to me. Since I made a segue using the storyboard I was able to make the segue full screen by following the seccond answer in this post: Presenting modal in iOS 13 fullscreen
Within my app, I want to create a user profile controller, which can be navigated to from several different controllers. I would like it to have a back button that will take the user back to whichever controller they came from.
How do I do this?
Dismiss
Add UIButton for back navigation somewhere to your UserProfileController. Then in UserProfileController create action and set it as action of your button. This action dismisses your UserProfileController (so you get back to previous UIViewController)
#IBAction func backButtonPressed(_ sender: UIButton) {
dismiss(animated: true, completion: nil)
}
UINavigationController
Alternatively you can have previous ViewControllers embed in UINavigationController. Then you will be able to tap to back button (which is set by default) in UINavigationBar which gets you to previous UIViewController
suppose I have a MainTabBarController, from one of it's tabs, I go to FirstViewController, then from FirstViewController, I go to SecondViewController (all with present modally), in SecondViewController when user hits cancel button, I want to go back to MainTabBarController, without showing FirstViewController, can I do this without NavigationController? cus I have no NavigationController in current version of my code and it will cost me many changes :(
in your SecondViewController you can call below code on tap of cancel button, which gets the presentingViewController of SecondViewController -> presentingViewController of FirstViewController which is a TabBarController and call dismiss on it.
#objc func dismiss(_ button: UIButton) {
self.presentingViewController?.presentingViewController?.dismiss(animated: true)
}
I'm new to swift and IOS development. I'm working on a tabbed application(3 views). For example, FirstView, SecondView and ThirdView. FirstView has a button that opens a addNewSession view and the addNewSession view has a Back button that back to the FirstView. The problem is Tab bar disappears after back from the addNewSession view
FirstView to addNewSession view.
#IBAction func toAddNew(sender: AnyObject) {
let addNewSession = self.storyboard?.instantiateViewControllerWithIdentifier("addNewSession") as addNew
self.presentViewController(addNewSession, animated: true, completion: nil)
}
addNewSession view to FirstView
#IBAction func backToPrev(sender: AnyObject) {
println("test1")
let FirstView = self.storyboard?.instantiateViewControllerWithIdentifier("FirstView") as FirstViewController
self.presentViewController(FirstView, animated: true, completion: nil)
}
The problem is your backToPrev method is instantiating a new FirstViewController, which is not the same instance you came from. You are not really going back to the original one, you are showing a new one. This is not what you want.
The proper way to do this is to embed the FirstViewController in a navigation controller, then push the addNew controller onto it. When you use a nav controller, you get the Back behavior for free.
Hopefully you are using a storyboard? Select your FirstViewController, go to the Editor menu and choose Embed in Navigation Controller.
In your toAddNew, instead of presentViewController use self.navigationController.pushViewController to push your addNew controller.
There's an even easier way to do this last step, using segues. You control drag in the storyboard from your button in FirstViewController to the addNew controller and create a Show segue. This will automatically show your addNew controller when the button is touched. With this approach, you will want to remove your toAddNew IBAction and the connection since it's redundant.
I have a navigation controller, with a table view. When I press a cell, the detail view controller opens.
In my root view controller I have :
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "detailview" {
var destination:DetailViewController = segue.destinationViewController as DetailViewController
destination.delegate=self
}
}
In my detail view controller I have a back button :
#IBAction func back() {
self.navigationController?.popViewControllerAnimated(true)
}
The issue is, after 2 go to and return, my app crashes when I go back on the root view controller pressing back button. The console doesn't give me errors. It just crashes.
I think I have forgotten to unwind the segue.
So in my detail view controller I added :
#IBAction func unwindToViewController(segue: UIStoryboardSegue) {
println("unwind function")
}
I connect this function to my back button with "exit" in my storyboard.
When I run my app, If I press on the back button, the console doesn't display my print "unwind function", so unwindToViewController isn't called. Why ?
And my app still crashes...
Your unwindToViewController method should be placed in your root viewController, then ctrl-drag from the button in the detailViewController to the Exit icon in InterfaceBuilder. Choose that method in the popup menu.
Another approach would be to declare a protocol with a function in the rootViewController that is called from the detailViewController. You already set the rootViewController as the delegate of the detailViewController. Within that function you call dismissViewController.
Swift answer...
I had a similar problem.
The func: "segueForUnwindingToViewController(toViewController: UIViewController, fromViewController: UIViewController, identifier: String?) -> UIStoryboardSegue" was never called.
Solution:
since I didn't have a "UINavigationController", because I simply embeded the app in a Navigation Controller, I created a UINavigationController subclass for the Navigation Controller and added the function named above on it. Now the app calls "segueForUnwindingToViewController"