I have an application that will direct user to another viewController once it is logged in.
DispatchQueue.main.async {
let controller = HomeViewController()
controller.isLoggedIn = self.loggedIn
controller.userRole = self.userRole
controller.username = self.username
let navigationController = UINavigationController(rootViewController: controller)
if #available(iOS 13.0, *) {
navigationController.isModalInPresentation = true
navigationController.modalPresentationStyle = .overFullScreen
} else {
// Fallback on earlier versions
}
print("should present here")
self.present(navigationController, animated: true)
}
Above is the "redirecting" part. This code works well in the simulator, but on the real device it does not work. Any idea how I can solve it? Thanks!
Try this also Set home screen identifier in storyboard "HomeViewController"
In code:
let controller = storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
Using .fullScreen as modalPresentationStyle should fix your issue and gives the default style used on iOS 12 or lower.
if #available(iOS 13.0, *) {
navigationController.modalPresentationStyle = .fullScreen
} else {
// Fallback on earlier versions
}
You need to use storyBoard reference for presenting a viewController. Which you can do by using example of the below attached code:-
let VC1 = self.storyboard.instantiateViewController(withIdentifier:"MyViewController") as! ViewController
`let navController = UINavigationController(rootViewController: VC1)` // Creating a navigation controller with VC1 at the root of the navigation stack.
self.present(navController, animated:true, completion: nil)
thanks for the response but I fixed it by
self.dismiss(animated: true) {
self.present(navigationController, animated: true)
}
apparently it didnt work as there was a error saying there was another view controller being presented ( i missed this error previously )
Related
I currently have a method that I use to setup a new ViewController
func setRootView(viewController vc: UIViewController){
UIApplication.shared.windows.first?.rootViewController = vc
UIApplication.shared.windows.first?.makeKeyAndVisible()
}
How can I modify the presentation that the ViewController will show over the other screen like presentation style not modally ?
That is the function that gets called after the button is pressed and the view should change:
func moveToNextVC(isLogin: Bool){
if self.checkNetworkConnection(){
let vc = HomeVC(nibName: "HomeVC", bundle: nil)
if isLogin{
vc.modalPresentationStyle = .automatic
vc.url = loginLink
}else{
vc.modalPresentationStyle = .automatic
vc.url = signupLink
}
setRootView(viewController: vc)
}
else{
showAlert("Alert!", message: "Please check your internet connection, then try again.")
}
}
Per Shawn Frank's comment:
Instead of doing this UIApplication.shared.windows.first?.rootViewController = vc, I would do present(vc, animated: true)
This solved the problem.
I am trying to present a view that is showd from the bottom to the top. This is my code
let myPageViewController = storyboard?.instantiateViewController(withIdentifier: "myPageViewControllerID") as! MyPageViewController
myPageViewController.modalPresentationStyle = .fullScreen
let navController = UINavigationController(rootViewController: myPageViewController)
navigationController?.present(navController, animated: true, completion: nil)
Despite I am using .fullScreen, the view is not presented on full screen.
I tried using peformSegue to show the view with this code
self.performSegue(withIdentifier: "myPageViewSegue", sender: nil)
the page is presented on fullscreen but from the left to the right and not from the bottom to the top.
The third code I tried is this one
let detailVC = MyPageViewController()
let navigationController = UINavigationController(rootViewController: detailVC)
navigationController.modalPresentationStyle = .fullScreen
present(detailVC, animated: true)
here I get an error Application tried to present modally an active controller. I tried to add self.dismiss when disappearing MyPageViewController but it didn't helped.
The problem maybe is you are not presenting navigationController you are presenting detail vc, Use this
'let detailVC = MyPageViewController()
let navigationController = UINavigationController(rootViewController: detailVC)
navigationController.modalPresentationStyle = .fullScreen
present(navigationController, animated: true)'
if problem still exists use
navigationController.modalPresentationStyle = .overCurrentContext
Try this one:
let detailVC = MyPageViewController()
detailVC.modalPresentationStyle = .fullScreen
present(detailVC, animated: true)
You could try this, worked for me:
Setup up your segue:
performSegue(withIdentifier: "myPageViewSegue", sender: self)
Then use the prepare for segue method:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destVC = segue.destination as! MyPageViewSegue
destVC.modalPresentationStyle = .fullScreen
}
I ran into this problem and was stumped. Then I realized that overriding dismiss also overrides .fullscreen
// This breaks .fullscreen
override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
super.dismiss(animated: flag, completion: completion)
// do something
}
It's clear that you don't need this if .fullscreen is being used, but leaving it in place caused problems.
You need to change your code with below lines and then Booom work like a charm
let vc = MyPageViewController()
vc.modalPresentationStyle = .fullScreen
present(vc, animated: true)
let detailVC = MyPageViewController()
let navigationController = UINavigationController(rootViewController: detailVC)
navigationController.modalPresentationStyle = .overCurrentContext
present(detailVC, animated: true, completion: nil)
Explanation:
Its very simple. Its better to explain it line by line. Line 1: Declare the viewcontroller. Line 2: Add Navigation Controller (its optional. If you don't need, then you may skip navigation bar). Line 3: We have defined the modal presentation style link as overCurrentContext. and present the navigationController (it will come up with navigation bar and viewcontroller) or only the viewcontroller as per your need. In this piece of code, you will get the viewcontroller without navigation bar.
Error text:
Application tried to present modally an active controller.
Moreover, all elements seem to be called for the first time. The application crashes most likely due to the navigation controller. How can I fix this error?
#objc private func taskButtonTouched(){
let vc = TaskVC()
let navigationController = OptionalNC(rootViewController: vc)
navigationController.modalPresentationStyle = .fullScreen
self.present(vc, animated: true, completion: nil)
}
You must present OptionalNC insetead TaskVC
#objc private func taskButtonTouched(){
let vc = TaskVC()
let navigationController = OptionalNC(rootViewController: vc)
navigationController.modalPresentationStyle = .fullScreen
self.present(navigationController, animated: true, completion: nil)
}
Sometimes, navigationController?.pushViewController method is not working while debugging. My initial controller (self) has already navigation controller. However, we could not see any error log in output screen. Have you ever encountered this problem ? Is might be a memory problem ?
let controller = storyboard.instantiateViewController(withIdentifier: "MyViewController") as! MyViewController
self.navigationController?.pushViewController(controller, animated: true)
Environment: iOS 12, Xcode 10.1
Regards,
try
DispatchQueue.main.async {
self.navigationController?.pushViewController(controller, animated: true)
}
Please make sure you have set navigation Controller as initial View controller
Then you can use this piece of code for moving between controllers
let controller = storyboard.instantiateViewController(withIdentifier: "MyViewController") as! MyViewController
self.navigationController?.pushViewController(controller, animated: true)
To get back to the controller using Navigation use
self.navigationController?.popViewController(animated: true)
self.dismiss(animated: true, completion: nil)
And I Hope it is not a memory Problem.
Is there any way to dismiss all the view controllers ( in which some controllers are pushed through navigation) and go back to the root view controller. I saw lots of examples but they didn't work in my application. I am using swift 4
This is code in appdelegate
func setNavigationToRootViews(){
storyBoard = UIStoryboard(name: "Main", bundle: nil)
nav = storyBoard?.instantiateViewController(withIdentifier: "mainNavigation") as! UINavigationController?
let accessToken: String? = KeychainWrapper.standard.string(forKey: "token")
print(accessToken as Any)
if accessToken != nil {
let homeVc = storyBoard?.instantiateViewController(withIdentifier: "Home-VC") as! HomeViewController
nav?.pushViewController(homeVc, animated: false)
}else{
let welcomVc = storyBoard?.instantiateViewController(withIdentifier: "login-VC") as! LoginViewController
nav?.pushViewController(welcomVc, animated: false)
}
let leftMenuVC = storyBoard?.instantiateViewController(withIdentifier: "menu-VC") as! MenuViewController
container = MFSideMenuContainerViewController.container(withCenter: nav, leftMenuViewController: leftMenuVC, rightMenuViewController: nil)
container?.panMode = MFSideMenuPanModeNone
window?.rootViewController = container
window?.makeKeyAndVisible()
}
and this in my last View controller
#IBAction func okayBtnTapped(_ sender: Any) {
_ = self.navigationController?.popToRootViewController(animated:
true)
dismiss(animated: true, completion: nil)
}
Try this one:
self.navigationController?.popToRootViewController(animated: true)
You can just set a new RootController like this:
let storyboard = UIStoryboard(name: "sName", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "<YOUR ROOT CONTROLLER>")
self.window?.rootViewController = viewController
If you don't have a window at self.window you need to instanciate one based on your AppDelegate.
If you're within a NavigationController you can also use the answer of #Anshul Bhatheja
Check you navigation controller, and view controllers inside that navigation controller. It seems debugging issue.
this method popToRootViewController(animated:) is the method should work
If you are working with simple push navigation controller and you want to go back to root view controller then you simply have to write
_ = self.navigationController?.popToRootViewController(animated: true)
extension UINavigationController {
func popToViewController(ofClass: AnyClass, animated: Bool = true) {
if let vc = viewControllers.filter({$0.isKind(of: ofClass)}).last {
popToViewController(vc, animated: animated)
}
}
func popViewControllers(viewsToPop: Int, animated: Bool = true) {
if viewControllers.count > viewsToPop {
let vc = viewControllers[viewControllers.count - viewsToPop - 1]
popToViewController(vc, animated: animated)
}
}
}
pop to SomeViewController class
navigationController?.popToViewController(ofClass: SomeViewController.self)
pop 2 view controllers
navigationController?.popViewControllers(viewsToPop: 2)