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]
}
Related
I have 3 view controllers: VC1 -> VC3 -> VC2. Transit from VC3 to VC2 I made by next code:
let storyboard = UIStoryboard(name: "VCs", bundle: nil)
let myVC2 = storyboard.instantiateViewController(withIdentifier: "VC2") as? VC2
myVC2?.name = "Test"
self.navigationController?.pushViewController(myVC2!, animated: true)
In viewDidLoad() of VC2 I delete VC3 from viewControllers stack and left only VC1:
var navigationVCs = self.navigationController?.viewControllers
navigationVCs!.remove(at: 1)
self.navigationController?.viewControllers = navigationVCs!
All work well. But I have one visual "Issue". When the view controller moves from VC4 to VC3, and VC3 view starts a load, NavigationBar back button of VC3 first of all show title of VC4, and only then switches to VC1 title. How I can fix this and force VC2 show back button title of VC1? Thanks.
You can pass through the back button title of VC1 to VC2 in the VC3 this way:
if let navigationController = UIApplication.shared.keyWindow?.rootViewController as? UINavigationController {
if let previousVC = navigationController.viewControllers.first {
let backItem = UIBarButtonItem()
let title = previousVC.navigationItem.backBarButtonItem?.title
backItem.title = title
navigationItem.backBarButtonItem = backItem // This will show in the next view controller being pushed
}
}
before you call
self.navigationController?.pushViewController(myVC2!, animated: true)
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
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
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);
}
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)