Reputation: 572
I have presented ViewController1 using this code:
let vc1 = ViewController1()
present(vc1, animated: true, completion: nil)
Now, I want to show ViewController2 in ViewController1.
@IBAction func buttonEvent(_ sender: UIButton) {
let vc2 = ViewController2()
self.present(vc2, animated: true, completion: nil)
}
The problem is: I want to show the ViewContoller2 while the current ViewController is being dismissed when the button event is called.
And I want to animation while doing this.
Thank you.
Upvotes: 19
Views: 26315
Reputation: 563
If your app uses AppDelegate, SceneDelegate and Storyboard, assign an identifier to the ViewController you wish to replace the current vc with
// replace viewController
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let destinationViewController = storyboard.instantiateViewController(identifier: "MyViewControllerIdentifier")
UIApplication.shared.windows.first!.rootViewController = destinationViewController
Upvotes: 2
Reputation: 2826
var viewControllers = self.navigationController?.viewControllers
viewControllers[viewControllers.count - 1] = newViewController
self.navigationController?.setViewControllers(viewControllers!, animated: true)
Upvotes: 2
Reputation: 517
You can create a function in SceneDelegate
, modify the root view controller and access it with (UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?.yourFunctionHere(view: UIViewController)
. unless your app doesnt use a navigation controller or a tab view you can probly just use a presetSegue() function.
https://fluffy.es/how-to-transition-from-login-screen-to-tab-bar-controller/
Upvotes: 0
Reputation: 2754
You may achieve this through navigationController
as follows:
guard var viewControllers = sourceViewController.navigationController?.viewControllers else { return }
// Popped ViewController not used
_ = viewControllers.popLast()
// Push targetViewController
viewControllers.append(targetViewController)
sourceViewController.navigationController?.setViewControllers(viewControllers, animated: true)
Get viewControllers
in your navigation stack at first. Pop the current and append the target one. Then, set your stack to updated viewControllers
.
(For those who do not use navigationController
)
I realized a possible problem in the given answer. Thus I want to make this addition. Check documentation of parent before continue. I want to lay emphasis on this part:
If the recipient is a child of a container view controller, this property holds the view controller it is contained in. If the recipient has no parent, the value in this property is nil. Prior to iOS 5.0, if a view did not have a parent view controller and was being presented, the presenting view controller would be returned. On iOS 5, this behavior no longer occurs. Instead, use the presentingViewController property to access the presenting view controller.
In brief, if you want to dismiss the current UIViewController
(sourceViewController
) and present the next one (targetViewController
), you should make the present()
call from presentingViewController
of the current.
weak var presentingViewController = self.presentingViewController
sourceViewController.dismiss(animated: true, completion: {
presentingViewController?.present(targetViewController, animated: false, completion: nil)
})
Though you probably see the transition this time, at the end of the completion
of sourceViewController
's dismiss()
, the presentingViewController
will be shown till the targetViewController
is presented. I don't know whether you expect this behavior. If no, I couldn't come up with a workaround to prevent this for now.
Upvotes: 30
Reputation: 61
this worked for me
viewControllers = self.navigationController?.viewControllers
viewControllers.remove(at: viewControllers.count - 1)
self.navigationController?.setViewControllers(viewControllers, animated: true)
self.performSegue(withIdentifier: "destinationVC", sender: self)
Upvotes: 6