View controller added in app delegate not appearing - ios

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let auth: UIViewController =
storyBoard.instantiateViewController(withIdentifier: "Auth") as UIViewController
window?.rootViewController?.present(auth, animated: true, completion: nil)
return true
}
I get the error...
Warning: Attempt to present
on whose view is not in the
window hierarchy!
I presume the root controller has not been properly configured at this point in the app life cycle.
How do I do this? I want to avoid having the root controller having to check whether it needs to show the login screen.

You can do it like that:
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if Settings.appSettings.authToken != nil {
self.showMainController()
}
NotificationCenter.default.addObserver(forName: .authorizationOperationDidSuccess,
object: nil, queue: nil) { (notification) in
self.showMainController()
}
return true
}
private func showMainController() {
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let controller: UIViewController =
storyBoard.instantiateViewController(withIdentifier: "Main") as UIViewController
if self.window == nil {
self.window = UIWindow(frame: UIScreen.main.bounds)
}
self.window?.backgroundColor = UIColor.white
self.window?.rootViewController = controller
self.window?.makeKeyAndVisible()
}
private func showAuthorizationController() {
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let controller: UIViewController =
storyBoard.instantiateViewController(withIdentifier: "Auth") as UIViewController
if self.window == nil {
self.window = UIWindow(frame: UIScreen.main.bounds)
}
self.window?.backgroundColor = UIColor.white
self.window?.rootViewController = controller
self.window?.makeKeyAndVisible()
}
On successful login make
NotificationCenter.default.post(name: .authorizationOperationDidSuccess,
object: nil)

Make change here,
let auth: AuthVC = storyBoard.instantiateViewController(withIdentifier: "Auth") as AuthVC
// AuthVC is your_VC_name
Still facing issue, you can ask.

Related

new ViewController is not displaying when pushed in AppDelegate [duplicate]

This question already has an answer here:
Xcode 11 & iOS13, using UIKIT can't change background colour of UIViewController
(1 answer)
Closed 3 years ago.
Here is my code to present a ViewController from app delegate in swift 5, I have done everything the same as everyOne else But the new ViewController is not shown when app is launched.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let welcome = mainStoryboardIpad.instantiateViewController(withIdentifier: "Welcome") as! WelcomeScreen
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = welcome
self.window?.makeKeyAndVisible()
return true
}
Put it in
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let welcome = mainStoryboardIpad.instantiateViewController(withIdentifier: "Welcome") as! WelcomeScreen
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = welcome
self.window?.makeKeyAndVisible()
return true
}
UPDATE:
If it is not working try:
if let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main){
if let welcome = mainStoryboardIpad.instantiateViewController(withIdentifier: "Welcome") as! WelcomeScreen{
//Does it come here?
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = welcome
self.window?.makeKeyAndVisible()
}
}
Make sure you actually get in to the body if most inner if which is if let welcome = mainStoryboardIpad.instantiateViewController(withIdentifier: "Welcome") as! WelcomeScreen

How to Navigate another page when application launch first time in swift 3

I am implementing an iOS app. when User Launch the application first time, I need to navigate to another page and from next time onwards I need to navigate Home Page. How to do this task in iOS swift?
Updated: if you get this error: "Value of type 'AppDelegate' has no member 'window' ".
Answer is : you have to write your codes inside of SceneDelegate.swift
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let defaults = UserDefaults.standard
guard let a=UserDefaults.standard.object(forKey: "wantOverview") else {
let storyBoard = UIStoryboard.init(name: "Main", bundle: nil)
let initialVc = storyBoard.instantiateViewController(withIdentifier: "firstTimeViewController") as! firstTimeViewController
self.window?.rootViewController = initialVc
self.window?.makeKeyAndVisible()
defaults.set(false, forKey: "wantOverview")
return
}
let storyBoard = UIStoryboard.init(name: "Main", bundle: nil)
let initialVc = storyBoard.instantiateViewController(withIdentifier: "ViewController") as! ViewController
self.window?.rootViewController = initialVc
self.window?.makeKeyAndVisible()
guard let _ = (scene as? UIWindowScene) else { return }
}
The following solution to this common problem assumes that
At the outset — in this example, that's before the "username" key has been set in the user defaults — we want to launch to the storyboard's Initial View Controller (where the user is supposed to set the "username" key).
Thereafter, we always want to launch to a different view controller in the storyboard, whose identifier in this example is "root".
It's very short and simple!
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if let rvc = self.window?.rootViewController {
if UserDefaults.standard.object(forKey:"username") as? String != nil {
self.window!.rootViewController = rvc.storyboard!.instantiateViewControllerWithIdentifier("root")
}
}
return true
}
}
This can be achieved using userdefaults. Just make a new controller like SplashViewController which will only redirect to desired ViewController.
import UIKit
class SplashViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
decideWhichScreenToShow()
}
// This logic will do
func decideWhichScreenToShow(){
if !UserDefaults.standard.bool(forKey: "your_key"){
// This will execute first time, in that controller's viewDidLoad() make this true
}else{
}
}
}
You can write same logic in Appdelegate.
Create func for checking that if your key in UserDefaults or not using this link & Then check by if...else
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
if isKeyPresentInUserDefaults(key: "isFirstTime") {
let home = HomeVC()
window?.rootViewController = home
} else {
let login = LoginVC()
window?.rootViewController = login
UserDefaults.standard.set(true, forKey: "isFirstTime")
}
return true
}
func isKeyPresentInUserDefaults(key: String) -> Bool {
return UserDefaults.standard.object(forKey: key) != nil
}
Try this:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if firstTime = UserDefaults.standard.object(forKey: "firstTime")
{
let storyboard = UIStoryboard(name: "SecondStoryBoard", bundle: nil)
let MainView = storyboard.instantiateViewController(withIdentifier: "SecondTimeViewController") as! SecondTimeViewController
let navController = UINavigationController.init(rootViewController: MainView)
self.window?.rootViewController = navController
}
else
{
UserDefaults.standard.set(true, forKey: "firstTime")
let storyboard = UIStoryboard(name: "FirstStoryBoard", bundle: nil)
let MainView = storyboard.instantiateViewController(withIdentifier: "FirstTimeViewController") as! FirstTimeViewController
let navController = UINavigationController.init(rootViewController: MainView)
self.window?.rootViewController = navController
}
}
You may use change the didFinishLaunchingWithOptions method in AppDelegate to achieve this.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
guard let firstTime = UserDefaults.standard.object(forKey: "IsFirstTime") else {
UserDefaults.standard.set(true, forKey: "IsFirstTime")
let storyBoard = UIStoryboard.init(name: "FirstStoryBoard", bundle: nil)
let initialVc = storyBoard.instantiateViewController(withIdentifier: "FirstControllerId") as! FirstTimeViewController
self.window?.rootViewController = initialVc
self.window?.makeKeyAndVisible()
return true
}
let storyBoard = UIStoryboard.init(name: "Main", bundle: nil)
let initialVc = storyBoard.instantiateViewController(withIdentifier: "NormalInitialController") as! ViewController
self.window?.rootViewController = initialVc
self.window?.makeKeyAndVisible()
return true
}
You check if the value for key, "IsFirstTime", exists in UserDefaults. There won't be a value if the app is launching for the first time.
In this case, you can launch your FirstTimeViewController and set a value to the key in UserDefaults.
If a value exists in UserDefaults, just initiate your normal ViewController.

Use of undeclared type "ViewController"

I'm using a library for Tap Bar Controller so I have to change the name of the class controller to RAMAnimatedTabBarController to use the features. But in app delegate when I want to present the main bar it displays this error
Use of undeclared type "RAMAnimatedTabBarController"
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if UserDataSingleton.sharedDataContainer.logged == "logged" {
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewControlleripad : UIViewController = mainStoryboardIpad.instantiateViewController(withIdentifier: "Order") as! RAMAnimatedTabBarController // error here
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = initialViewControlleripad
self.window?.makeKeyAndVisible()
}else{
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewControlleripad : UIViewController = mainStoryboardIpad.instantiateViewController(withIdentifier: "loginViewController") as! loginViewController
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = initialViewControlleripad
self.window?.makeKeyAndVisible()
}
You need to import it first. At the beginning of the file, use:
import RAMAnimatedTabBarController

Launch ViewController from AppDelegate, tabbar missing from bottom

I am developing my first app, where I am trying to manage a session in my app, where I am trying to check if user has logged in recently. If user has logged in recently, then I want to skip login page, and move him to next page.
Here what I am doing, however I am unable to proceed forward
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let viewControllerB = mainStoryboard.instantiateViewControllerWithIdentifier("account") as! AccountDetails
let navController = UINavigationController(rootViewController: viewControllerB)
let appDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
appDelegate.window?.rootViewController = viewControllerB
let vc = self.window?.rootViewController
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(navController, animated: true, completion: nil)
return true
}
I am able to get to the desired view,but the Tabbar on that view is missng. I want to restore the same.
Second Screen (My Account which I want to show)
class AccountDetails: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
// Initialize Tab Bar Item
tabBarItem = UITabBarItem(title: "Account Details", image: UIImage(named: "Account.png"), tag: 1)
}
}
Replace the line self.window?.rootViewController?.presentViewController(navController, animated: true, completion: nil)
with
self.window?.rootViewController = navController
Change window's rootViewController:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
if(User loggin last time) {
let yourTargetViewController = UIViewController()
yourTargetViewController.view.backgroundColor = UIColor.redColor()
self.window?.rootViewController = yourTargetViewController
}
return true
}
This is the working solution
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let viewControllerB = mainStoryboard.instantiateViewControllerWithIdentifier("tabbar") as! UITabBarController
let navController = UINavigationController(rootViewController: viewControllerB)
let appDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
appDelegate.window?.rootViewController = viewControllerB
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(navController, animated: true, completion: nil)
//tabbar is the storyboard ID of tabbarcontroller

How can I change the initial ViewController in LaunchScreen with Swift?

I want to check whether the user is logged in or not, if the user is logged in, then bring him to main screen, or show the welcome screen.
You can't do in Launch Screen, but you can achieve same in AppDelegate's method didFinishLauchingWithOption, there you can check if user logged in or not and set the root view controller and don't set initialViewController in storyboard.
It should be something like this
NSString *identifier = isLoggedIn ? #"IdentifierForVC1" : #"IdentifierForVC2";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier: identifier];
self.window.rootViewController = vc;
Code is not tested in an editor may have some
Swift code should be like this
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier(identifier) as! UIViewController
self.window?.rootViewController = vc
Swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "Identifier")
let navigationController = UINavigationController(rootViewController: viewController)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
return true
}
You can't do it in Launch Screen but can do in AppDelegate
for Swift 4
if userLoggedIn == True {
//Do something
} else {
//Do something
}
UserDefaults.standard.set(value:Bool ,forKey:"loggedIn") //This will save the bool value to your UserDefaults
}
Now Go to your AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
if (UserDefaults.standard.bool(for key: "loggedIn")) == true {
let welcomeVC = mainStoryboard.instantiateViewController(withIdentifier: "welcomeVC") as! WelcomeVC
self.window?.rootViewController = newRootVC
self.window?.makeKeyAndVisible()
} else {
let loginVC = mainStoryboard.instantiateViewController(withIdentifier: "loginVC") as! LoginVC
self.window?.rootViewController = newRootVC
self.window?.makeKeyAndVisible()
}
return true
}
Happy Coding
Hope this helps :)
Write this code in AppDelegate Swift 4.0
In didFinishLaunchingWithOptions pass your viewController to self.launch(rootController: ViewController())
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let frame = UIScreen.main.bounds
self.window = UIWindow(frame: frame)
self.window!.rootViewController = ViewController()
self.window!.makeKeyAndVisible()
return true
}
Write this code in AppDelegate Swift 5.0 Xcode 11.0
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _ = (scene as? UIWindowScene) else { return }
if let windowScene = scene as? UIWindowScene{
let window = UIWindow(windowScene: windowScene)
let rootViewController = UIStoryboard(name: "Auth", bundle: nil).instantiateViewController(withIdentifier: "LoginViewController") as! UINavigationController
window.rootViewController = rootViewController
self.window = window
window.makeKeyAndVisible()
}
}
In Swift, in your AppDelegate.swift,
self.window?.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("{INSERT_STORYBOARD_ID_HERE}") as? UIViewController

Resources