I am developing a application which has login screen and verify code screen. Once user logged in,and logout I need to show only login screen so how can I manage the navigation view controller. Right now, my verifycode view controller is coming first before showing the login view controller when I am pressing the sign out button.
Could you please let me know how can I manage the view controller?
You can use this method didFinishLaunchingWithOptions (AppDelegate):
self.window = UIWindow.init(frame: UIScreen.main.bounds)
if (User.isLogged) {
window?.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "loginVC") as! LoginVC
} else {
window?.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController()!
}
self.window?.makeKeyAndVisible()
Create class User when you can storage information about status user (Authorized or not) and in didFinishLaunchingWithOptions check this status and set rootViewController for window.
Related
I have some firebase code with a listener set up in AppDelegate and a log out set elsewhere. It is not taking me to the login view controller when I click sign out.
Logout Code:
#IBAction func logOutTapped(_ sender: Any) {
try! Auth.auth().signOut()
}
App Delegate Code:
let authListener = Auth.auth().addStateDidChangeListener { auth, user in
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
self.window = UIWindow(frame: UIScreen.main.bounds)
if user != nil
{
...//Some code
}
else
{
print("Headed to login view controller.")
let loginViewController = storyBoard.instantiateViewController(withIdentifier: "loginViewController") as! LoginViewController
self.window?.rootViewController = loginViewController
self.window?.makeKeyAndVisible()
}
I know the sign out code is calling the "else" in app delegate, because my logs are printing "Headed to login view controller" when I press logout. However, the login view controller is never displayed. It stays on the screen where the user clicks log out. When the app is stopped and started again, the login screen is displayed. The storyboard identifier is correctly set as loginViewController.
Any ideas?
Always when I focus out (click on the "Home" button), Sign In page is displayed.
How to change the default picture when the app is out of focus?
Add following code in applicationWillResignActive function in Appdelegate
let storyboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let navigationController:UINavigationController = storyboard.instantiateInitialViewController() as! UINavigationController
let rootViewController:UIViewController = storyboard.instantiateViewController(withIdentifier: "You_Signin_Page") as UIViewController
navigationController.viewControllers = [rootViewController]
self.window?.rootViewController = navigationController
This will set "Your_Signin_Page" as yourrootViewController everytime you press the home button
I am using Xcode 11 and Swift 5.
Upon receiving an APNS notification, I need to jump to a view controller deep in my storyboard from AppDelegate. This viewController (chatVC) is behind a tabbar and a navigation controller and several other view controllers. See the image below. I know how to check the notification for tags and how to use launchOptions in AppDelegate to trigger the jump. But I am struggling with how to establish the context for that last view controller so that the user can use the back button all the way back to the tab bar controller.
I have read many SO answers, and tried many approaches but none seem to have the same embedding of a nav controller inside a tab bar controller. Here is my code in AppDelegate (after reading the tag in the notification):
if tag == "CS" {
// Set up a Chat View Controller.
if let chatVC = UIStoryboard(name: "Main", bundle: .main).instantiateViewController(withIdentifier: Constants.Storyboard.chatVC) as? NewChatViewController,
let tabBarVC = UIStoryboard(name: "Main", bundle: .main).instantiateViewController(withIdentifier: Constants.Storyboard.tabBarController) as? UITabBarController,
let csVC = UIStoryboard(name: "Main", bundle: .main).instantiateViewController(withIdentifier: Constants.Storyboard.csViewController) as? CustomerServiceViewController,
let helpVC = UIStoryboard(name:"Main", bundle: .main).instantiateViewController(withIdentifier: Constants.Storyboard.helpVC) as? HelpViewController
{
// Set the customer service document Id.
chatVC.cs = cs
// Make the tabBarVC the Root View Controller
self.window?.rootViewController = tabBarVC
self.window?.makeKeyAndVisible()
// Select the Favorites Index.
tabBarVC.selectedIndex = 0
// Push the Customer Service VC on top.
tabBarVC.show(csVC, sender: Any?.self)
// Push the Help VC on top of Customer Service VC.
csVC.show(helpVC, sender: Any?.self)
// Push the the chat detail page on top.
helpVC.show(chatVC, sender: Any?.self)
}
}
}
return true
What can I do to jump to the chatVC and set up the navigation context beneath it so the back button can be used?
Here is how you can do it:
guard let tabBarVC = UIApplication.shared.windows.filter( {$0.rootViewController is UITabBarController } ).first?.rootViewController as? UITabBarController else { return }
tabBarVC.selectedIndex = 0 //you can select another tab if needed
guard let chatVC = UIStoryboard(name: "Main", bundle: .main).instantiateViewController(withIdentifier: Constants.Storyboard.chatVC) as? NewChatViewController else { return }
if let navController = tabBarVC.viewControllers?[0] as? UINavigationController {
navController.pushViewController(chatVC, animated: true)
}
You can also pass objects from your notification to your chatVC here before pushing it, in case you need to do that.
Hope this works for you!
The structure of my project is as follows.
Initially when the user is registering or trying to login the initial navigation controller should work and after successfully registering / loggin in the user should be taken to first tab of tab bar controller. But the issue that i am facing is that i am getting 2 navigation bars in the tab bar view. Can someone guide me how to implement this in the correct way.
Thanks in advance
At some point, I would assume that the app is able to determine whether the user loggedin or not, based on that you have to set the desired root view controller for the app.
For such a case, the best place to do that is application(_:didFinishLaunchingWithOptions:) method in the AppDelegate file:
Tells the delegate that the launch process is almost done and the app
is almost ready to run.
For simplicity, let's say that you are saving isLoggedin boolean in the UserDefault, so it could be achieved like this:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// the flag for determining whether the user loggedin or not
let isLoggedin = UserDefaults.standard.bool(forKey: "K_isLoggedin")
// the desired initial view controller (based on the value of `isLoggedin`)
let initialViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: isLoggedin ? "TabbarIdentifier" : "FirstNavigationIdentifier")
// setting the app rootViewController
window?.rootViewController = initialViewController
return true
}
Note that "TabbarIdentifier" represents the tabbar controller at the storyboard and also "FirstNavigationIdentifier" represents the first navigation view controller at the storyboard.
if you are unaware of how to set the view controller identifier, checking this answer should help.
Technically speaking, setting the desired root view controller means setting the rootViewController to the main window of the app (AppDelegate window).
Make one of the two navigation controllers from tabbar to initial viewcontroller and add the following in Appdelegate's didFinishLAunching
if (isDashboardVC == nil || isDashboardVC == false)
{
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let navigationController:UINavigationController = mainStoryboardIpad.instantiateViewController(withIdentifier: "navigationmain") as! UINavigationController
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
}
else
{
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let tabBarIntial : UITabBarController = mainStoryboardIpad.instantiateViewController(withIdentifier: "Tabbarcontroller") as! UITabBarController
let navigationController2:UINavigationController = mainStoryboardIpad.instantiateViewController(withIdentifier: "yourViewControllerName") as! UINavigationController
let navigationController:UINavigationController = mainStoryboardIpad.instantiateViewController(withIdentifier: "yourViewControllerName") as! UINavigationController
let navigationController3:UINavigationController = mainStoryboardIpad.instantiateViewController(withIdentifier: "yourViewControllerName") as! UINavigationController
tabBarIntial.viewControllers = [navigationController2, navigationController, navigationController3]
tabBarIntial.selectedIndex = 1
}
I have a tab bar controller as my initial view controller in storyboard (with the arrow). However when a user signs in the first time, I'm trying to change the initial view controller programmatically in didFinishLaunchingWithOptions: to start out at a navigation controller to go through a couple VCs for them to enter signup information (I don't want a tab bar for this). Although I'm changing the initial VC in my app delegate, I'm getting a crash with Could not cast value of type 'UITabBarController' (0x1031374f8) to 'UINavigationController' (0x1031374a8). I was under the impression that the initial VC would be changed and not reference the Tab Bar Controller at all? Is there a way I can accomplish changing the initial VC without the Tab Bar Controller being referenced? Here is my code in didFinishLaunchingWithOptions:, any help is GREATLY appreciated!
if User.current() == nil {
let storyboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let navigationControllerr:UINavigationController = storyboard.instantiateInitialViewController() as! UINavigationController
let initialViewController = storyboard.instantiateViewController(withIdentifier: "SplashPageVC")
navigationControllerr.viewControllers = [initialViewController]
self.window?.rootViewController = navigationControllerr
}
Why dont you try something like this.
if User.current() == nil {
let initialViewController = storyboard.instantiateViewController(withIdentifier: "SplashPageVC")
let navigationController = UINavigationController(rootViewController: initialViewController)
self.window?.rootViewController = navigationControllerr
}