Navigation Controlled embedded in Container View custom segue - ios

I have UIContainerView inside which I have UINavigationController and other VC embedded in UINavigationController (7 of them).
So, it looks like this:
On that 7 screens inside UINavigationController I'm calling a popup screen which then should redirect to other screen, from which user can perform back segue to the VC popup was called from.
So, user journey inside UINavigationController will look like:
Opened VC1(2,3,5,6,7) -> Called popup VC -> Pressed button -> opened VC4 -> pressed navigation back button -> returned to VC1.
Here's my code:
#IBAction func didPressAuthors(_ sender: UIButton) {
self.dismiss(animated: true) {
if let navigation = UIApplication.shared.keyWindow?.rootViewController as? UINavigationController {
let vc1 = self.storyboard!.instantiateViewController(withIdentifier: "FirstVC")
let vc2 = self.storyboard!.instantiateViewController(withIdentifier: "SecondVC")
let vc3 = self.storyboard!.instantiateViewController(withIdentifier: "ThirdVC")
let vc4 = self.storyboard!.instantiateViewController(withIdentifier: "FourthVC")
let vc5 = self.storyboard!.instantiateViewController(withIdentifier: "FifthVC")
let finalVC = self.storyboard!.instantiateViewController(withIdentifier: "Authors")
let userJourney = self.defaults.array(forKey: DefaultKeys.screenID.rawValue)
for vcName in userJourney! {
switch String(describing: vcName) {
case "FirstVC":
self.journeyVC.append(vc1)
case "SecondVC":
self.journeyVC.append(vc2)
case "ThirdVC":
self.journeyVC.append(vc3)
case "FourthVC":
self.journeyVC.append(vc4)
case "FifthVC":
self.journeyVC.append(vc5)
default:
self.journeyVC.append(finalVC)
}
}
self.journeyVC.append(finalVC)
navigation.setViewControllers(self.journeyVC, animated: true)
}
}
}
Problem:
When I didn't have UINavigationController inside UIContainerView this code worked just fine, but after I had added Container View - it stopped. Dismiss func is called, but nothing happens. What I'm missing? Should I change how VC is presented?
Would be grateful if anyone could help me fix this issue. Many thanks and have a nice weekend!

Your current root isn't the navigation here
if let navigation = UIApplication.shared.keyWindow?.rootViewController as? UINavigationController {
it's a usual VC that the navigation is inserted as a child so try
if let root = UIApplication.shared.keyWindow?.rootViewController as? RootVC {
let nav = root.children![0] as! UINavigationController

Related

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]
}

Swift ios check which viewcontroller is present

I wonder how I can check what view controller that is currently displayed.
When a user recivies a notification and press on it I want to take the user to a certain VC. But only if the user is not already there.
I am using this when I get a notification:
if let tabBarController = self.window!.rootViewController as? CustomTabBarController {
let navInTab:UINavigationController = tabBarController.viewControllers?[0] as! UINavigationController
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let destinationViewController = storyboard.instantiateViewController(withIdentifier: "EventVc") as? EventsViewController
navInTab.pushViewController(destinationViewController!, animated: true)
tabBarController.selectedIndex = 0
}
I dont want to run this code if the user already is in EventVc
Also, can I run the code above if the user already is in tab 0 but in a different VC than EventVc?
And if it is any help my app is built like this:
(root) TabBar
(tab1) -> navigation controller -> vc -> vc...
(tab2) -> navigation controller -> vc -> vc...
(tab3) -> navigation controller -> vc -> vc...
(tab4) -> navigation controller -> vc -> vc...
this function should solve your problem, just send index number as an argument (forexample: 0 for tab1, 1 for tab2 etc.) at it navigates you selectedIndex ViewController.
// Navigation TabIndex TabBar View Controller
fileprivate func goTabIndex(index: Int) {
let storyboard = UIStoryboard(name: "yourTabbarStoryboardID", bundle: nil)
let tabBarController = storyboard.instantiateViewController(withIdentifier: "EventVc") as! UITabBarController
tabBarController.selectedIndex = index
self.window?.makeKeyAndVisible()
DispatchQueue.main.async {
self.window?.rootViewController?.present(tabBarController, animated: false)
}
}
You can find the Presenting ViewController like this;
let presentingVC = self.window?.rootViewController?.presentingViewController
Presented ViewController;
let presentedVC = self.window?.rootViewController?.presentedViewController

How to instantiate a navigation and tab controller from another view controller which is in segue(show detail)?

I've asked a question before and it works successfully thanks to the one of the answers How to instantiate a navigation controller from another view controller?, but I have come across a new problem which is , whenever i click a button from a show detail segue, it supposed to navigate to a normal tab with a navigation bar, but it did nothing.
Here's the storyboard
Here's the scenario
1) User click on a button on a firstViewController and it will segue to a thirdViewController which is in show detail
2) User click another button which will then supposed to go to a secondViewController with the codes below
Here's the code
in ThirdViewController
#IBAction func buttonTapped(sender: UIButton) {
guard let tabBarController = tabBarController else { return }
let navController = tabBarController.viewControllers![1] as! UINavigationController
let secondViewController = navController.topViewController as! SecondViewController
secondViewController.name = "My name is TDog"
tabBarController.selectedIndex = 1
}
What did i do wrong? Do i still need to instantiate?
You have to dismiss the actual ThirdViewController but, in this class, you dont know yet UITabViewController so a way to obtain it ( not to re-instantiate but to recall from memory) is to call the rootViewController of your window (it can be done in your project):
#IBAction func buttonTapped(sender: AnyObject) {
self.presentingViewController!.dismissViewControllerAnimated(true, completion: nil)
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let tabBarController = appDelegate.window!.rootViewController
if tabBarController is UITabBarController {
let tab = tabBarController as! UITabBarController
let navController = tab.viewControllers![1] as! UINavigationController
let secondViewController = navController.topViewController as! SecondViewController
secondViewController.nameString = "My name is TDog"
tab.selectedIndex = 1
}
}
You got to call
self.presentingViewController.dismissViewControllerAnimated(true, completion: nil)
after the following line
tabBarController.selectedIndex = 1

Presenting VC embedded in a NavController from AppDelegate

I'm trying to want to present/push a VC embedded in a NavController from AppDelegate. I previously used this code but somehow it's not working anymore:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let VC = storyboard.instantiateViewControllerWithIdentifier("PendingRequest") as! PendingRequestVC
let navController = UINavigationController.self(rootViewController: VC)
let rootViewController = UIApplication.sharedApplication().keyWindow!.rootViewController
rootViewController!.presentViewController(navController, animated: false, completion: nil)
Other codes open my desired VC but not within a navigation pane. Any guidance would be appreciated.
Calling from AppDelegate after user interacts with push notification.
Edit:
I'm able to present the right VC by using this code:
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
if let viewController = mainStoryboard.instantiateViewControllerWithIdentifier("PendingNavController") as? UINavigationController {
if let yourViewController = viewController.topViewController as? PendingRequestVC {
//yourViewController.getRequestdata()
}
UIApplication.sharedApplication().keyWindow!.rootViewController = viewController;
}
But this code won't allow me to go back using the Close button on my NavBar.
My structure is as follow:
TabController -> NavController1 -> VC1 -> NavController1a -> VC1a
I'm trying to get to VC1a and be able to use the Closed button to go back to VC1
Add a UIButton in your presented ViewController's View. Following event will be performed by that button. You can dismiss your Navigation Controller this way
#IBAction func dismissViewController(sender: AnyObject) {
self.navigationController.dismissViewControllerAnimated(false, completion:nil);
}

Resources