Replace rootViewController behind a modal view - ios

With the following code I'm able to change the rootViewController behind a modal view :
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let signupVC = storyboard.instantiateViewControllerWithIdentifier("SignupNavigationController") as! UINavigationController
let landingPageVC = storyboard.instantiateViewControllerWithIdentifier("LandingPage") as! LandingPageViewController
presentViewController(signupVC, animated: true, completion: {
UIApplication.sharedApplication().delegate?.window??.rootViewController = landingPageVC
UIApplication.sharedApplication().delegate?.window??.sendSubviewToBack(landingPageVC.view)
})
When I close my modal view controller it's the previous rootViewController that is displayed (only during the animation). Then my new view controller is displayed properly.
Any idea how I could prevent this ?

Answering to myself,
The view I can see during the modal animation is something like a snapshot. I found out that the view is not visible in Xcode's view hierarchy debugger, thus the view is not present in the viewController tree.
To refresh this snapshot I had to set the modalPresentationStyle to .OverFullScreen
myModalViewController.modalPresentationStyle = .OverFullScreen

Related

How to present a popup view in full screen

I've following view configuration
Tab bar -> Nav controller -> View: Click on a button -> segue to-> Another view: Click on a button -> Popup view.
This modal view is on a different storyboard.
I want to present this model view in full screen. I've tried this solution mentioned on Presenting modal in iOS 13 fullscreen but it doesn't work. I've also tried few other solutions but the popup view is not showing over full screen, status bar is visible at the top.
How do I present modal view in a full screen?
let storyboard = UIStoryboard(name: "Other", bundle: Bundle.main)
guard let popupVC = storyboard.instantiateViewController(withIdentifier: "PopUpViewController") as? PopUpViewController else {
print("PopUpViewController not found")
return
}
popupVC.modalPresentationStyle = .fullScreen
self.present(popupVC, animated: true, completion: nil)
You could try presenting with the navigation controller.
let storyboard = UIStoryboard(name: "Other", bundle: Bundle.main)
guard let popupVC = storyboard.instantiateViewController(withIdentifier: "PopUpViewController") as? PopUpViewController else {
print("PopUpViewController not found")
return
}
var navigationController = UINavigationController(rootViewController: popupVC)
navigationController.modalPresentationStyle = .fullScreen
self.present(navigationViewController, animated: true, completion: nil)
An alternative would be to use presentViewController but presentViewController will only present one viewController modally over the currently visible viewController whereas presenting with the navigationController will give the flexibility to push further components on top, providing a smoother navigation experience with go back to previous page kind of behaviour.
Maybe try creating the view controller this way:
let popOverVC = UIStoryboard(name: "yourBoard", bundle: nil).instantiateViewController(withIdentifier: "YourViewController") as! YourViewController
self.addChild(popOverVC)
let lSs = UIScreen.main.bounds
popOverVC.view.frame = CGRect(x: 0, y: 0, width: lSs.width, height: lSs.height)
popOverVC.view.tag = tag
self.view.addSubview(popOverVC.view)
popOverVC.didMove(toParent: self)
Within the popup view controller class, add a method for animating its view in viewDidLoad.
Edit: I read your replies. The issue you are having is caused by not handling the status bar properly. Instead of trying to make this veiewcontroller fullscreen, simply hide the status bar
How do I hide the status bar in a Swift iOS app?
and bring it back when you want to see it again.

How to go back to the initial ViewController the right way?

I have a few view controllers with navigation bar and tab bar. Then I have an initial view controller with no navigation bar and tab bar. I want to go back to the initial view controller with no other view controllers in stack. Here's what I do:
// Head back to Initial View Controller.
let initialViewController = self.storyboard!.instantiateViewController(withIdentifier: "Initial")
UIApplication.shared.keyWindow?.rootViewController = initialViewController
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = initialViewController
This works perfectly. But then it doesn't move to another view controller from the initial view controller again. For example:
#IBAction func loginButton(_ sender: Any) {
print("Login Button Tapped.")
let storyboard = UIStoryboard(name: "SignInViewController", bundle: nil)
let signInViewController = storyboard.instantiateViewController(withIdentifier: "SignInViewController") as! SignInViewController
self.navigationController?.show(signInViewController, sender: nil)
}
Here, the print statement is run, but self.navigationController.show won't. How do all this work? And what's the right approach to accomplish this?
EDIT:
To avoid any confusion, here's my storyboard. The left most viewcontroller (pink screen) is the initial view controller I want to go back to. The right most on the same level is the view where I want to go back from.
It doesn't move to another view controller, because you are setting a simple view controller in your rootViewController.
What you need is:
let initialViewController = self.storyboard!.instantiateViewController(withIdentifier: "Initial")
let navController = UINavigationController.init(rootViewController: initialViewController)
UIApplication.shared.keyWindow?.rootViewController?.present(navController, animated: true, completion: nil)
This will create a navigationviewcontroller, so when on "Initial" you should be able to perform push, present actions of another view controllers.
From your initial view controller, you need to instantiate your navigation stack and present it modally. Then, when you want to get back to your pre-navigation initial VC, just call dismiss(animated:,completion:), which will dismiss your entire navigation stack and return you to the initial view controller.
self.navigationController.popToRootViewController(animated:) is what you're looking for.
https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621855-poptorootviewcontroller
EDIT
Try dismissing the navigationController after calling popToRoot.
self.navigationController.dismiss(animated: true, completion: nil)
EDIT
Try the following:
#IBAction func loginButton(_ sender: Any) {
print("Login Button Tapped.")
let storyboard = UIStoryboard(name: "SignInViewController", bundle: nil)
let signInViewController = storyboard.instantiateViewController(withIdentifier: "SignInViewController") as! SignInViewController
present(signInViewController, animated: true, completion: nil)
//self.navigationController?.show(signInViewController, sender: nil)
}
Then to dismiss the signInViewController call self?.navigationController.dismiss(animated:true, completion:nil) from inside the signInViewController.

Opening a View Controller that is connected to a navigation Controller programatically

I am using AKSwiftSlideMenu as basis for an app.
I have a view controller (HomeVC) that is connected to a navigation controller.
If the storyboard entry point is pointing to HomeVC then I get the menu of course, but my app needs to start without the menu and only after certain screens and tasks that are done i want to navigate to HomeVC and allow user access to the menu.
I noticed that if a i place a button on a starting view controller that does not have a connection to the navigation controller, and connect that button directly to the Navigation controller by drag+cntrl then pressing the button will get me from a view controller without a menu to HomeVC and show the menu.
How do i do that programmatically
Thanks in advance for any help
edit: I have tried the following code
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "Home") as! UINavigationController
self.present(newViewController, animated: true, completion: nil)
which did not work resulting with the following err
Could not cast value of type 'myApp.HomeVC' (0x10a159280) to 'UINavigationController' (0x10cc2d3c8).
let newViewController = storyBoard.instantiateViewController(withIdentifier: "Home") as! UINavigationController
s
"Home" is not a UINavigationController. Remove as! UINavigationController from this line and the error will go away.
thank you Daniel for telling me to instantiate navigation controller. Ended up giving navigation controller a storyboard id named ccontroller and the following code does what I needed
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "ccontroller") as! UINavigationController
self.present(vc, animated: true, completion: nil)

How to show a ViewController (not modally) within a UITabViewController

I want to show a ViewController within a UITabController but not display it modally. In the app, there's a home screen with a bunch of buttons that segue to other ViewControllers. The other view controllers are embedded in a navigation controller. I now have a need to show one of the ViewControllers from a TodayExtension. In my app delegate I have this but it presents the RequestorViewContoller modally without the tab structure or the navigation control.
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let requestor = mainStoryboard.instantiateViewController(withIdentifier: "RequestStoryboardID") as! RequestorViewController
let rootViewController = self.window!.rootViewController as! UITabBarController
rootViewController.present(requestor, animated: false, completion: nil)
Like what you mention, if the selectedViewController of the UITabBarController is a UINavigationController, you could do a pushViewController instead.
First, you will have to get the currently on screen UINavigationController. Then perform a pushViewController with requestor as a parameter.
presentedNavigationController = rootViewController.selectedViewController as! UINavigationController
presentedNavigationController.pushViewController(requestor, animated: true)

iOS Swift - Presenting View Controller sliding down while presenting new View Controller

I present a View Controller in the following fashion:
let vc: ChangeDateViewController = storyboard!.instantiateViewControllerWithIdentifier("changedate") as! ChangeDateViewController
let navigationController = UINavigationController(rootViewController: vc) //ensures that the top navigation bar remains in the new View Controller
self.presentViewController(navigationController, animated: true, completion: nil)
For some reason, the base presenting View Controller slides down while the new View Controller is sliding up. Although the presenting works, it does look glitchy because the sliding down reveals the black background behind the views. Is this a common occurrence, and is there anything I can do to prevent it?
Try this:
let storyboard1 = UIStoryboard(name: "Main", bundle: nil)
let conn = storyboard1.instantiateViewControllerWithIdentifier("changedate") as! LMAddaccountMainVC
self.presentViewController(conn, animated: true, completion: nil)
This might be helpful to solve you issue.

Resources