As you can see i have an initial view controller with label in it "Initial ViewController". In this view controller i use below code to go to selected tab of Tab Bar Controller
let vc1 = sb.instantiateViewController(withIdentifier: "tabbar") as! UITabBarController
vc1.selectedIndex = selected
let controllers = [vc1]
navigationController!.setViewControllers(controllers, animated: true)
In my First View, there's a button "Present VC" which presents "Presented View".
let vc1 = sb.instantiateViewController(withIdentifier: "PresentedVC") as! PresentedVC
present(vc1, animated: true, completion: nil)
Now i want to go back from presented vc to root vc(Initial View Controller). I can do this with:
let viewController = self.storyboard?.instantiateViewController(withIdentifier: "FirstNavigationController") as! FirstNavigationController
UIApplication.shared.keyWindow?.rootViewController = viewController
but this instantiate Initial View Controller every time and views remain in memory. How can i go back to Initial View Controller without instantiating it?
PS: FirstNavigationController is initial Navigation Controller.
At the very beginning you remove the initial view controller by doing this:
navigationController!.setViewControllers(controllers, animated: true)
All the previous viewControllers are gone now and replaced with the tabbar controller and its children.
If you want to go back to the initial controller, you will have to push the tabbar onto the stack instead of replacing everything with it. E.g.
navigationController?.pushViewController(tabbarVc, animated: true)
First when you did this
navigationController!.setViewControllers(controllers, animated: true)
the initial VC is deallocated (if it has not a strong references)
to keep it you can use push , pop instead of setViewControllers but note it may cause memory issues if you have heavy processing in your app as it will remain in navigationController stack
You are missing the concept between "Presenting" or "Setting" View Controller & "Navigating" the View Controller. You will get the answer, once you understood the concept. Here, it is..
When you are setting the ViewController, you are completely replacing the stack container to the new view controller. the way you did it here:
navigationController!.setViewControllers(controllers, animated: true)
In this case, STACK holds the addresses of the latest set/presented ViewControllers that means previous whole ViewController vanished.
On the other hand, if you are navigating to other view controller by pushing it. you can go back to previous controller by simple popping the ViewController address from stack. or to next ViewController by pushing
e.g:
self.navigationController?.pushViewController(tabbarVc, animated: true)
self.navigationController?.popViewController(animated: true)
Summary:
If you push TabBarController then, only you will get InitialVC.
Now, in your case, you are setting the ViewController and hence, you are not getting InivtialVC. Try Pushing tabbarVC This will work.
navigationController?.pushViewController(tabbarVc, animated: true)
Related
What is the difference between this first call:
let next = self.storyboard?.instantiateViewController(withIdentifier: "AFVC") as! AddFileViewController
self.present(next, animated: true, completion: nil)
and this second:
let dashboard = self.storyboard?.instantiateViewController(withIdentifier: "DBVC") as! DashboardViewController
self.navigationController?.pushViewController(dashboard, animated: true)
The first usage will present the new view controller. This presentation normally slides the new controller up from the bottom. If you want to go back, you need to create a button or something similar to dismiss it.
The second usage will use the navigation controller to display (via push which normally slides in from the right) the new view controller. You will automatically get a "< Back" button in the navigation bar. But this will only work if the calling view controller is already embedded in a navigation controller, otherwise self.navigationController is nil.
We are looking to change the way a user logs out of our app. In order to do that, we want to dismiss all the VCs below the current VC and put another VC on top as the root VC. Right now we are doing this which I believe does not dismiss any VC below from memory.
let viewController = storyboard?.instantiateViewController(withIdentifier: "SignIn")
if let unwrappedViewController = viewController {
self.present(unwrappedViewController, animated: true, completion: {})
}
The problem is that the VC that we want to put on top is not embedded in a Navigation Controller or tab bar controller. How would we dismiss the VCs and set the new VC as the main VC as if the user was opening the app for the first time without having previously logged in? We also do want the transition to be animated with whatever animation is normal for that event (modal animation is fine). I have read a bunch of different ways on doing it but I want to know which way is best practice and should be implemented specifically dismissing all VCs and putting a new VC that isn't in a Nav controller on top.
If you can access the UIWindow of the app, you can set its rootViewController property to your sign-in view controller, effectively removing all current view controllers and adding the sign-in view controller instead. Here's an example:
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
// Should remove all subsequent view controllers from memory.
appDelegate.window?.rootViewController.dismiss(animated: true, completion: nil)
// Set the root view controller to a new instance of the sign in view controller.
appDelegate.window?.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SignIn")
From some ViewController of my UINavigationController stack I present another ViewController and will never come back, but the problem is that deinit{} is not called. How should I remove each ViewController from the stack before navigation? Or should I use some other method? Now my code looks like
let destinationVC = storyboard?.instantiateViewControllerWithIdentifier("revealViewController") as! SWRevealViewController
self.presentViewController(destinationVC, animated: true, completion: nil)
First of all, when you call presentViewController:animated:completion: you will present the new viewController modally, outside of the navigationController's hierarchy.
If you wish to present it within the navigationController hierarchy use:
self.navigationController!.pushViewController(destinationVC, animated: true)
And if you want to change the view hierarchy, the navigationController has a property viewControllers which can be set with or without animation.
self.navigationController!.setViewControllers([destinationVC],
animated: true)
See the iOS Developer Library for more information.
I am trying to display a fix navigation bar for my UiTableViewController, I have a first ViewController and when I click on it, this will open my UITableViewController Here is the code of the click :
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("MyTableViewController") as! MyTableViewController
vc.myObject = object // I pass some data
presentViewController(vc, animated: true, completion: nil)
the UItableView is correctly display but not navigation bar appear, if I add one, the navigation bar scroll with the table view and I don't want this behavior.
I tried this without success :
Go to the Editor menu, and click on the Embed In submenu, and choose
Navigation Controller
And tried to change some settings here :
Actually, in your case you want to show navigation and for navigation you have to push your view controller to a UINavigationController thats why the solution is :
let vc = storyboard.instantiateViewControllerWithIdentifier("MyTableViewController") as! MyTableViewController
vc.myObject = object // I pass some data
self.navigationController?.pushViewController(vc, animated: true)
presentViewController offers a mechanism to display a modal view controller; i.e., a view controller that will take full control of your UI by being superimposed on top of a parent controller & establish a parent child relation b/w presenting & presented view controllers.
where as
pushViewController offers a much more flexible navigation process where you can push & pop a new controller to UINavigationController, so to go back to the previous one, in a ordered way. Imagine that controllers in a navigation controller will just build a sequence from left to right like building a stack of view controllers stacking upon each other.
Do it this way:
let vc = storyboard.instantiateViewControllerWithIdentifier("MyTableViewController") as! MyTableViewController
vc.myObject = object // I pass some data
self.navigationController?.pushViewController(vc, animated: true)
I tried to push to a view controller from a view class using tap gesture action. All the below lines are executed, but the control not pushing to respective view controller. I need to push to that view controller, but not to set the controller as root view,because i need to navigate back to some other navigated view controller. Any one please help me.
let webViewController = R2WebViewViewController()
currentWindow.rootViewController?.navigationController?.pushViewController(webViewController, animated: true)
try this
(currentWindow?.rootViewController as! UINavigationController).pushViewController(webViewController, animated: true)
Your root must be navVC
currentWindow.rootViewController?.navigationController?
Your problem is that your rootViewController is probably an UINavigationController already, so you should do:
let webViewController = R2WebViewViewController()
(currentWindow.rootViewController as? UINavigationController).pushViewController(webViewController, animated: true)