Swift ios reset viewcontroller hierarchy - ios

In storyboard my app is designed as:
Navigation VC -> VC1
What I am trying to do is to segue to another VC but reset the menu-hierarchy so that i dont have the old VC's stacked in the backgound
What I want to do is:
Navigation VC -> VC1 -> VC2 -> NEW VC with Navigation reseted
So when a user logs in and enters the account VC/Page the navigation stack should be resetted when hitting the account VC/Page
Is this possible to do?

If you do not want to add the view controllers to your navigation controller, every View controller you navigate to you can set that as the root view controller of your navigation controller and it won't be added in your stack.
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
let yourViewController: ViewController = storyboard.instantiateViewControllerWithIdentifier("respectiveIdentifier") as! ViewController
let navigationController = self.view.window?.rootViewController as! UINavigationController
navigationController.setViewControllers([yourViewController], animated: true)

My solution same as above but one line less
let yourViewControllerObejct = self.storyboard?.instantiateViewControllerWithIdentifier("YourViewControllerId") as? YourViewController
let navigationController = self.view.window?.rootViewController as! UINavigationController
navigationController.setViewControllers([yourViewControllerObejct!], animated: true)

Related

Skip login screen from scene delegate in tabbed bar navigation App

I am trying to skip the login screen and go straight to the MainViewController when the user is logged in. However the problem is that I have a Tab Bar Controller and Navigation Controller between the login and the main vc. After extensive search I wrote the below code
func showMainViewController() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let mainViewController: MainViewController = storyboard.instantiateViewController(withIdentifier: "MainViewController") as! MainViewController
let navigationController = UINavigationController(rootViewController: mainViewController)
//It removes all view controllers from the navigation controller then sets the new root view controller and it pops.
window?.rootViewController = navigationController
// //Navigation bar is hidden
// navigationController.isNavigationBarHidden = true
}
However it fails to show the tab bar view controller. Any help is appreciated.
try this
func showMainViewController() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let mainViewController: MainViewController = storyboard.instantiateViewController(withIdentifier: "TabBar")
window?.rootViewController = mainViewController
window?.makeKeyAndVisible()
}
you should instantiate TabBar no main viewController. since is instantiate inmediatrly is if first index or set the selected index

Segue to a View Controller from my AppDelegate removes my UI Tab Bar

I am having a problem when performing segue from my AppDelegate. I am using this code to do a segue from appdelagate:
let storyboard = UIStoryboard(name: "MyStoryboard", bundle: nil)
let viewController: MyViewController = storyboard.instantiateViewController(withIdentifier: "myviewcontroller") as! MyViewController
let rootViewController = self.window!.rootViewController as! UINavigationController
rootViewController.show(viewController, sender: self)
When I use this, my UITabBar is removed. I want to segue to a ViewController that is not a TabBar item and retain my UITabbar. I am also using navigation. How should I approach this?
To show the tab , you need to do the push from 1 of the tab vcs , and it should be embeded inside a navigation and use
let nav = self.window!.rootViewController as! UINavigationController
if let tab = nav.viewControllers.first as? UITabBarController ,
let innerNav = tab.viewControllers.first as? UINavigationController {
innerNav.pushViewController(viewController,animated:true)
}

Open specific View Controller in swift

I have implemented firebase notification in my app. When I click the notification i want to open specific vc. The hierarchy of vc is this,
TabBarController -> TabBarVC1 -> 1VC -> 2VC
Now, I want to go to 2VC when I click the notification. I have tried the code it goes fine but the hierarchy of VC's disturbs, when I moves there then it does not comes back. This is how i open 2VC.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "2VC")
self.present(controller, animated: true, completion: nil)
I want it to open 2VC but its hierarchy should not be disturb.
When I click back button on 2VC than it should move back to 1VC.
Do this
let vc1 = // alloc vc 1
let vc2 = // alloc vc 2
let vc3 = // alloc vc 3
let nav_Controllr = // alloc UINavigationController
// Now add your previous vc in NavigationController first
nav_Controllr.viewControllers.append(vc1)
nav_Controllr.viewControllers.append(vc2)
// Now push to the vc where you wanted navigate
nav_Controllr.pushViewController(vc3, animated: true)
Now your navigation stack is like this
vc1 -> vc2 -> vc3
when you pop your controller then it always be in this flow.
vc3 => vc2 => vc1
To have a back button then you need to make the root vc of the tabBar a navigationController
Entry Point -> TabBar -> Tab1 -> NavigationController - > VC1 -> VC2
then use this from vc1
self.navigationController?.pushViewController(vc2, animated: true)
if you want to open it from AppDelelgate call back of notification receive then use
if let tab = self.window?.rootViewController as? UITabBarController {
let vc1 = //////
let vc2 = //////
let nav = tab.viewControllers![0] as! UINavigationController
nav.viewControllers = [vc1,vc2]
}

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)

Load Tab Bar Controller from AppDelegate

I have been trying to figure this out by myself, but couldn't.
I want to load a Tab Bar controller from my AppDelegate (After a successful Google Sign in to the application).
I read here how to load a ViewController from AppDelegate
Perform Segue from App Delegate swift
Code in the example:
// Access the storyboard and fetch an instance of the view controller
let storyboard = UIStoryboard(name: "Main", bundle: nil);
let viewController: MainViewController = storyboard.instantiateViewController(withIdentifier: "ViewController") as! MainViewController;
// Then push that view controller onto the navigation stack
let rootViewController = self.window!.rootViewController as! UINavigationController;
rootViewController.pushViewController(viewController, animated: true);
In this example, my TabBar needs both a name and identifier, from what I understood.
Can someone please explain this to me ? I can't find "identifier" on the Tab Bar Controller , only "Title".
Also, I don't have a navigation controller view in my app.
set storyboard ID here
and embed the firstViewController in IB in navigationController
let rootViewController = self.window!.rootViewController as! UINavigationController;
rootViewController.pushViewController(viewController, animated: true);
iOS 13 Update
From version. iOS 13,
The RootViewController will be initiated in scene function located at
SceneDelegate.swift instead of AppDelegate.swift file. which looks like this.
Example:
// Simple init
let mainSB: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let loggedInTabController = mainSB.instantiateViewController(identifier: "loggedInTabController")
self.window!.rootViewController = loggedInTabController

Resources