How to change a viewcontroller of a slidemenu? - ios

I have 2 separate VC-s that each need to be displayed to the user depending on a state of the app. This is how I create my original slidemenu in AppDelegate, it works as intended:
let mainVC = MainNavVC.create()!
let leftMenuVC = LeftMenuVC.create()!
slideMenuController = SlideMenuController(mainViewController: mainVC, leftMenuViewController: leftMenuVC)
self.window?.rootViewController = slideMenuController
self.window?.makeKeyAndVisible()
But when I try to change the leftMenuVC the screen goes black, the menu button just stops working and tapGesture still shows the wrong menu. Here is a code I call to change the slidemenu:
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.slideMenuController?.leftViewController = AnotherLeftMenuVC.create()!
appDelegate.window?.rootViewController = appDelegate.slideMenuController
I also tried an alternative approach to change the leftMenuVC:
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.slideMenuController = SlideMenuController(mainViewController: MainNavVC.sharedInst!,
leftMenuViewController: AnotherLeftMenuVC.create()!)
appDelegate.window?.rootViewController = appDelegate.slideMenuController
appDelegate.window?.makeKeyAndVisible()
This will turn my screen black but tapGesture will at least show the correct leftMenu.
How to make this work ?

You can try this trick. I tested it in your library's sample project. This works but it's up to you to clean the code and make the unwrapping optionals and castings safer.
Basically the trick is to embed your leftController or rightController into a UINavigationController. And access such navigationController using the way you're trying to access the slideMenuController in the AppDelegate. And then replace the viewControllers of that navigationController.
In the viewDidLoad() of the MainViewController (I'm talking about the sample project, you should be familiar with this or relate your mainController here). I have this block of code that will be executed in 5 seconds ;) I use this approach when testing something, just to save time for the sake of demo.
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.registerCellNib(DataTableViewCell.self)
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(5)) {
let appDel = UIApplication.shared.delegate as! AppDelegate
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let rightViewController = storyboard.instantiateViewController(withIdentifier: "RightViewController") as! RightViewController
((appDel.window?.rootViewController as! ExSlideMenuController).leftViewController as! UINavigationController).viewControllers = [rightViewController]
}
}
and in the appDelegate, I embed the controller into a navigationController:
let slideMenuController = SlideMenuController(mainViewController:nvc, leftMenuViewController: UINavigationController(rootViewController: leftViewController), rightMenuViewController: rightViewController)
This should help you out.

Related

When should I set rootViewController? it's very confused

Hi I am struggling with rootViewController I left some code fragment with an explanation below, please let me know.
If I do it like below, it works and every things fine.
private func presentLogin() {
log.info("presenting login..")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let vc = storyboard.instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
vc.modalPresentationStyle = .fullScreen
appDelegate.window!.rootViewController = vc
present(vc, animated: false)
}
right after that if I execute the code below, ios shows nothing but white blank page..
private func presentMain() {
log.info("presenting main..")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let vc = storyboard.instantiateViewController(withIdentifier: "MainTabBarController") as! MainTabBarController
vc.modalPresentationStyle = .fullScreen
appDelegate.window!.rootViewController = vc
present(vc, animated: false)
}
but when I deleted the code
appDelegate.window!.rootViewController = vc
everything is fine.
In other words, the code below works only the first time.
appDelegate.window!.rootViewController = vc
why? what am I missing?, I don't understand..
It seems there are a lot of bugs concerning the exchange of the root view controller. Switching the root view controller is also a little uncommon way of "navigation". I would recommend a different approach:
Upon app startup, use a "launch" view controller. This is your root view controllers, and it stays to be your root view controller all the time
if login is required, present a login view controller
after successful login, dismiss the login view and go on
if logged in, present the main application's entry view

First ViewController from Tabbar cover the safe area(Status bar)

After sucessful signin i am opening Tabbar with follwing code
let mainView = UIStoryboard(name:"Main", bundle: nil)
let tabbar = mainView.instantiateViewController(withIdentifier: "Tabbar") as? Tabbar
tabbar?.modalPresentationStyle = .fullScreen
self.present(tabbar!, animated: true, completion: nil)
Its open Tabbar with first index selected but first ViewController also cover the save area ...
and switching between the TabbarItems make it work fine ...
I am not able to understand why this happening only in one ViewController on first time open ... and how to tackle that.
Also tried following code but did't work ...
self.edgesForExtendedLayout = []
Its not the proper solution its a kind of hack ... I told in Question that its get automatically fixed after switching between TabbarItems ... so i just added Two lines right after opening Tabbar VC.
tabbar?.selectedIndex = 1
tabbar?.selectedIndex = 0
And know the complete code seems like this.
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let mainView = UIStoryboard(name:"Main", bundle: nil)
let tabbar = mainView.instantiateViewController(withIdentifier: "Tabbar") as? Tabbar
appDelegate.window = UIWindow(frame: UIScreen.main.bounds)
appDelegate.window!.rootViewController = tabbar
appDelegate.window!.makeKeyAndVisible()
tabbar?.modalPresentationStyle = .fullScreen
self.present(tabbar!, animated: true, completion: nil)
tabbar?.selectedIndex = 1
tabbar?.selectedIndex = 0

How to navigate Inner view controller from App delegate

in my app delegate this is how I navigate to my SWRevealViewController
let revealViewController = mainStoryboard.instantiateViewControllerWithIdentifier("RevealView") as? SWRevealViewController
self.window!.rootViewController = revealViewController
self.window?.makeKeyAndVisible()
I navigate to that inner view controller from the SWRevealViewController's FrontViewcontrollerlike this.
let secondViewController = self.storyboard?.instantiateViewControllerWithIdentifier("Read") as! ReadViewController
secondViewController.title = self.selectedTitle
self.navigationController?.pushViewController(secondViewController, animated: true)
Now in AppDelegate when receive a push notification I want to navigate this ReadViewController. and when I click the back button it should come back to the FrontViewController just like it happens in normal way. How can I do this in my notification delegates in AppDelegate
Please help me.
Thanks
Try this :
let yourVC = mainStoryboard.instantiateViewControllerWithIdentifier("Read") as! ReadViewController
let frontViewController = mainStoryboard.instantiateViewControllerWithIdentifier("frontViewController") as! FrontViewController
let navController = UINavigationController()
navController.viewControllers = [yourVC,frontViewController]
self.window!.rootViewController = navController
self.window?.makeKeyAndVisible()

UIApplication.sharedApplication().keyWindow?.rootViewController freezes my app

At some point in my app I need to go back to my main (i.e. home) ViewController. So I need to travel backwards into my navigation stack which by now is full with ViewControllers and NavigationControllers. So I do the following:
// to dismiss the current VC
self.navigationController?.popViewControllerAnimated(true)
// to go back home
UIApplication.sharedApplication().keyWindow?.rootViewController = homeNC
homeNC is a global var pointing to a NavigationController containing a storyboard instance of my main "home" ViewController.
It works, but partially. Meaning, it does take me back to my home ViewController but it then becomes unresponsive to touches and scrolling. Nothing responds, neither the navigationBar buttons nor the TableViewCells inside the home NC/VC. Xcode doesn't crash, just sits there waiting.
I can't figure out why. Can anyone think what I'm missing here?
** EDIT **
Maybe it's because I am embedding a nested VC inside my main (home) VC. Here's the code and what else I tried since:
homeNC = self.navigationController!
homeVC = self
let discoverVC: UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("DiscoverVC") as UIViewController
// embed discoverVC in this VC
self.addChildViewController(discoverVC)
self.view.addSubview(discoverVC.view)
discoverVC.didMoveToParentViewController(self)
// store self NC for using it by "thank you" VC to come back to home after payment
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
// navigates back but becomes unresponsive
appDelegate.window?.rootViewController = homeVC
// navigates back but becomes unresponsive
appDelegate.window?.rootViewController = homeNC
I also tried saving a reference to the appdelegate window with the following:
// Initialise sideMenu
window = UIWindow(frame: UIScreen.mainScreen().bounds)
let sideMenu = SSASideMenu(contentViewController: UINavigationController(rootViewController: MainViewController()), leftMenuViewController: LeftMenuViewController())
window!.rootViewController = sideMenu
window!.makeKeyAndVisible()
// get a reference to appdelegate's window so that we can navigate back later
mainWindow = window!
but again it doesn't navigate back when I do:
appDelegate.window?.rootViewController = mainWindow.rootViewController
Try this. I will work for you.
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.window?.rootViewController = mainVC
EDIT
I read out your edited question. Problem is occurring due to SSASideMenu. I updated my answer and I hope now it will work for you. You have to make two changes. First in AppDelegate.swift, make property of SSASideMenu like this:
var window: UIWindow?
var sideMenu: SSASideMenu!
Now your code will be changed to:
sideMenu = SSASideMenu(contentViewController: UINavigationController(rootViewController: MainViewController()), leftMenuViewController: LeftMenuViewController())
Now if you want to change the view-controller, you have to change the contentViewController of SSASideMenu like this:
func showDiscoverVC() {
//Instantiate ViewController
let discoverVC: UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("DiscoverVC") as UIViewController
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.sideMenu.contentViewController = UINavigationController(rootViewController: discoverVC)
}

how to dismiss instantiated navigation rootviewcontroller in swift

Below is my working code which I have used to instantiate my viewController
let myPage = self.storyboard?.instantiateViewControllerWithIdentifier("myViewController") as! myViewController
let myNav = UINavigationController(rootViewController: myPage)
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.window?.rootViewController = myNav
Could anyone help and provide a solution to dismiss myViewController?

Resources