I am new in swift.I want to move one screen to another but problem is when I go to another screen,old screen overrides in new screen.
here is my code
dispatch_async(dispatch_get_main_queue()) {
let appsDelegate = UIApplication.sharedApplication().delegate
appsDelegate?.window!!.rootViewController = nil
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewControllerWithIdentifier("launcherEntry") as! UINavigationController
appsDelegate?.window!!.rootViewController = nextViewController
}
If you use UINavigationController, you should push the second view(screen) onto the first one. Check out the offical guide.
According to your code old screen overrides because you have not a push a UIViewController into navigation controller.
Here you destroyee the exiting controller then set a new controller. So that previos controller is move from the memory.
Please show Apple docs for the UINavigationController.
Update:
Please use following code for set a root view controller then you can push view controller easily.
let navigationController:UINavigationController = storyboard.instantiateInitialViewController() as! UINavigationController
let rootViewController:UIViewController = storyboard.instantiateViewControllerWithIdentifier("ID_LoginVC") as! LoginVC
navigationController.viewControllers = [rootViewController]
self.window?.rootViewController = navigationController
As you are new , i will explain what will happen when your code will be executed.
App delegate will hold the current instance of our application. Setting root view controller is setting Main view controller of your application.
SO basically your code will replace the previous view controller with next one.
Now what you have to do,
We have Navigation controller to manage our navigation stack, that allow us to go back from where have initiated.
If you are Using storyboard , add your view controller into NavigationController, if you already know then ignore or follow this
SELECT your first view controller GOTO Editor in Xcode menu > Select EMBED IN option > NAVIGATION CONTROLLER. this will add your first view into navigation controller.
Now when you want to display next view controller, There are two ways to do so,
1)Using segue from Storyboard
Right click from view/button from where you want to show next view.
drag it to the next view controller and release the right click.
Select push
2)Programatically
you don't have to set root view controller, just push the next view controller in navigation controller you have
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewControllerWithIdentifier("launcherEntry") as! UINavigationController
Above line will intimate the textview controller, now we have to push this view controller, we can achieve this with
self.navigationController?.pushViewController(nextViewController, animated: true)
Related
I am looking to replace this code:
let homeViewController = storyboard?.instantiateViewController(identifier: Constants.Storyboard.homeViewController) as? HomeViewController
view.window?.rootViewController = homeViewController
view.window?.makeKeyAndVisible()
This code is how I change my view controllers programatically and I have been told it works but is not the best to use.
My storyboard is currently set out like this:
Everything left of the navigation controller needs to be controlled programatically as I do not want segues from sign up and login to the main page. However everything right of the navigation controller, I want to be controlled with segues, however when I do this it always presents modally. And that is why I am using that code snippet to change View Controllers.
EDIT:
I want to use segues and a navigation controller because I want to use the toolbar
The problem is that you are loading HomeViewController as the root view controller:
let homeViewController = storyboard?.instantiateViewController(identifier: Constants.Storyboard.homeViewController) as? HomeViewController
view.window?.rootViewController = homeViewController
view.window?.makeKeyAndVisible()
Instead, you want to load a UINavigationController as the root. Give the navigation controller in your storyboard an ID (such as "mainNavController") and change your startup code to:
let navController = storyboard?.instantiateViewController(identifier: Constants.Storyboard.mainNavController)
view.window?.rootViewController = navController
view.window?.makeKeyAndVisible()
Now, HomeViewController will be loaded as that navigation controller's "root" controller, and your segues will "push" instead of "present".
Note: I'm assuming your current code (with the optional storyboard? and view.window?) already working correctly.
You can change the way segue's present view controllers in your storyboard. You can change it to cover full screen so that it isn't modal. There are attributes on the right side you can experiment with.
I have a view controller as my initial view controller. there's a button in it(GO button) which when the user taps, it should go to another view controller(let's call it Destination view controller with label 'This is where i wanna go'). Meanwhile i want to pass it through a Tabbar controller. The reason is i want to have tabbar in my navigation stack.
I wish to go directly to the Destination view controller while pressing go button but it should show the tab bar items at the bottom.
So for achieving this in FirstViewController didLoadMethod I checked a bool value and pushed the view controller to the Destination view controller. I achieved the result I.e when pressing the Go button it goes to the Destination view controller and has tab bar items at it's bottom.
But the problem since it passes through the Tabbarcontroller the FirstViewController is shown for some seconds and then it pushes to the Destination view controller. I wish to hide FirstViewController while this transition takes place.
How to achieve this?
Picture shows what i want. what can I do to hide firstviewcontroller while having it in navigation stack?
I think this can be done in a simple way -
In the first viewController of the tab bar has a viewDidLoad() function or you can use loadView() which is called before the viewDidLoad() function. Push to the next viewController in the function.
Put your push navigation code in one of those functions
*You cant see the current view coltroller, it will push the screen to your required viewcontroller before loading the tab bar initial view contoller.
Hope it will work for you.
or >>>> you can check it out
let storyboard = UIStoryboard(name: "your_storyBoard_name", bundle: nil)
let viewController1 = storyboard.instantiateViewController(withIdentifier: "firstViewController")
let viewController2 = storyboard.instantiateViewController(withIdentifier: "secondViewcontroller")
let controllers = [viewController1, viewController2]
self.navigationController!.setViewControllers(self.navigationController!.viewControllers + controllers, animated: true)
The effect you're trying to produce is hard to do in a storyboard. Programmatically you would simply create the Tabbar Controller (with its children) and the "This is where I want to go" Controller, and then ask the navigation controller to show both at the same time.
For example, after "Go" is tapped, this is the code I would run inside your first view controller:
let tabBarController = UITabBarController()
let finalDestination = UIViewController()
var viewControllers = self.navigationController?.viewControllers ?? []
viewControllers.append(tabBarController)
viewControllers.append(finalDestination)
self.navigationController?.setViewControllers(viewControllers, animated: true)
Given the structure you shown, where the view controller A is the root view controller of the TabBar, you should push the second view controller B on the navigation stack inside either willAppear or didLoad of view controller A, according to your personal business logic (flag, conditions, etc.).
The trick here is to use either pushViewController or setViewControllers with animated: false so that the navigation stack will be set immediately during willAppear/didLoad and it won't show the push animation of B over A. This way, at onDidAppear the layout will be already fully rendered in it's final state: with B at the top of the navigation stack and no animations in progress.
Ok, i know that when applicationWillEnterForeground fires from my AppDelegate that I can trigger events. What I would like to do is force the app to show a certain view when It re-appears from the background. The view is a UIViewController called loginViewController and it has a storyboard Id of "initViewController"
My question is, what do I use in this function (applicationWillEnterForground) to make this view load when the app comes into focus again? Thanks.
I've never done this, but you can probably accomplish it by adding the UIViewController to the UIViewController stack, if you just want to add a view controller and show its view (see Case 1) or by replacing the root view controller, if you want to discard the existing view controller stack and use a new one (see Case 2)
Case 1) In the first case you need a reference to the UIViewController that you want to make its parent view controller. You can save this in a static variable somewhere or if you are just planning on showing a temporary view when the app restarts then you can get a reference to the root view controller use it as the parent:
// get a reference to the main storyboard
let mainSB = UIStoryboard(name: "Main", bundle: nil)
// get a reference to the root view controller
if let rootVC = UIApplication.sharedApplication().keyWindow?.rootViewController,
// get a reference to the view controller using identifier
initVC = mainSB.instantiateViewControllerWithIdentifier("initViewController") as? UIViewController {
// present the view controller
rootVC.presentViewController(initVC, animated: false, completion: nil)
}
When you are finished use logic from within the view controller to dismiss it, and your user should be back where they started:
self.dismissViewControllerAnimated(true, completion: nil)
Case 2) You can discard the existing view controller stack and start a new one by replacing the root view controller and building up the stack manually. Present the view controllers in order with animated parameter set to false.
// get a reference to the main storyboard
let mainSB = UIStoryboard(name: "Main", bundle: nil)
// get references to view controllers
if let vc1 = mainSB.instantiateViewControllerWithIdentifier("vc1") as? UIViewController,
vc2 = mainSB.instantiateViewControllerWithIdentifier("vc2") as? UIViewController {
// set root view controller
UIApplication.sharedApplication().keyWindow?.rootViewController = vc1
// build up the view controller stack by adding next vc
vc1.presentViewController(vc2, animated: false, completion: nil)
}
Navigation Controllers
If one of your view controllers is a navigation controller you will need to cast it as such, and then push any view controllers onto your navigation controller. Navigation controllers have their own stack.
if let myNavCon = mainSB.instantiateViewControllerWithIdentifier("nav") as? UINavigationController {
// push view controller onto navigation controller stack
myNavCon.pushViewController(someViewController, animated: false )
}
WARNING
This does not deal with the model of your app at all (only the UI). You will also need to set any data that you would have set in prepareForSegue, etc. An easy system to use when you have VCs you present both programmatically and via storyboard segues is to take the code that would have been in prepare for segue and move it to your own instance method that takes a reference to the child view controller as its parameter. Then you can call it from prepare to segue with the destination view controller or from code before you present the view controller.
None of this code has been tested. It was written directly via the website. It likely contains typos. Please let me know so I can fix any.
I would like to know what code is required to traverse the storyboard from a UIViewController located at index N of a UINavigationController which is embedded in a UITabBarController, to a similarly embedded UIViewController.
I would also like all UIViewControllers to be popped in the source UINavigationController
Direct segues (as shown in red) do not fit my use case.
Swift please.
You can pop to the root view controller then change the selected index of the index of the tab bar controller then push whatever view controllers you need on the other navigation controller. For example:
let tabBarController = self.tabBarController;
let indexZeroNavController:UINavigationController = self.tabBarController?.viewControllers![0] as! UINavigationController
self.navigationController?.popToRootViewControllerAnimated(true)
tabBarController?.selectedIndex = 0
let newViewController = self.storyboard?.instantiateViewControllerWithIdentifier("New View Controller")
let otherNewViewController = self.storyboard?.instantiateViewControllerWithIdentifier("Other New View Controller")
indexZeroNavController.pushViewController(newViewController!, animated: true)
indexZeroNavController.pushViewController(otherNewViewController!, animated: true)
Beyowulf's approach used to be valid, but things have changed. In the viewController you wish to pop to, define an "unwind segue". example Once it's defined, you can drag from a button to "exit" and select that unwind segue.
The way unwind segues work has been completely reworked in xcode 7, so you don't have to worry too much about the view controller stack.
I have a side menu with different navigation points. The first point is the Home nav. This should send the user back to the main view.
If I start the app, the main view will be generated by the storyboard. Now if a user taps on "Home", I would like to reuse this instance. Is this possible? (With Swift)
Thanks
You can instantiate a view from a storyboard like so:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let homeViewController = storyboard.instantiateViewControllerWithIdentifier("Home")
Then do as you will :)