Launch ViewController from AppDelegate, tabbar missing from bottom - ios

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

Related

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.

View controller added in app delegate not appearing

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.

iOS Empty Space above the navigation bar?

When I check and calling the Viewcontroller from Appdelegate my app shows empty space above navigation bar I don't know what is the reason.
Here I give the code and screen shot.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let checkUserid = UserDefaults.standard.value(forKey: "USERID")
if checkUserid != nil {
print(checkUserid!)
let mainStoryboard = UIStoryboard(name: "Main" , bundle: nil)
let revealViewController = mainStoryboard.instantiateViewController(withIdentifier: "RevealViewController") as? SWRevealViewController
let navigationController = UINavigationController(rootViewController: revealViewController!)
navigationController.navigationBar.isTranslucent = false
window!.rootViewController = navigationController
window!.makeKeyAndVisible()
}
else
{
let mainStoryboard = UIStoryboard(name: "Main" , bundle: nil)
let loginViewController = mainStoryboard.instantiateViewController(withIdentifier: "ViewController") as! ViewController
let navigationController = UINavigationController(rootViewController: loginViewController)
navigationController.navigationBar.isTranslucent = false
window!.rootViewController = navigationController
window!.makeKeyAndVisible()
}
}
I believe you need to hide the default navigation bar.
Try adding the following code:
navigationController.isNavigationBarHidden = true

How to go to the what I want controller when application didFinishLaunching

When I launching my application, I want go to the custom view controller, but the default first controller in storyboard:
I want go to brown vc when launch my app:
My method is below, but get a black screen with Unable to capture view hierarchy
1) In Info.plist, delete the Main storyboard file base name line.
2) In my Appdelegate.swift:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let sb:UIStoryboard = UIStoryboard.init(name: "Main", bundle: nil)
let nav: CustomNavController = sb.instantiateViewController(withIdentifier: "CustomNavController") as! CustomNavController
let red_vc:ViewController = sb.instantiateViewController(withIdentifier: "ViewController") as! ViewController
let green_vc:ViewController2 = sb.instantiateViewController(withIdentifier: "ViewController2") as! ViewController2
let brown_vc:ViewController3 = sb.instantiateViewController(withIdentifier: "ViewController3") as! ViewController3
nav.viewControllers = [red_vc, green_vc, brown_vc]
self.window? = UIWindow.init(frame: UIScreen.main.bounds)
self.window?.rootViewController = nav
self.window?.makeKeyAndVisible()
return true
}
Result get a black screen:
Is which step I mistake? and how can I get it well ? When launch my application I want go to brown vc.
ATTEMPT - 1
Using push to brown vc, it is not work too:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let sb:UIStoryboard = UIStoryboard.init(name: "Main", bundle: nil)
let nav: CustomNavController = sb.instantiateViewController(withIdentifier: "CustomNavController") as! CustomNavController
let red_vc:ViewController = sb.instantiateViewController(withIdentifier: "ViewController") as! ViewController
let green_vc:ViewController2 = sb.instantiateViewController(withIdentifier: "ViewController2") as! ViewController2
let brown_vc:ViewController3 = sb.instantiateViewController(withIdentifier: "ViewController3") as! ViewController3
//nav.viewControllers = [red_vc, green_vc, brown_vc]
nav.pushViewController(red_vc, animated: false)
nav.pushViewController(green_vc, animated: false)
nav.pushViewController(brown_vc, animated: false)
self.window? = UIWindow.init(frame: UIScreen.main.bounds)
self.window?.rootViewController = nav
self.window?.makeKeyAndVisible()
return true
}
You no need delete Main storyboard file base name in Info.plist
In AppDelegate:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let mainStoryboard = UIStoryboard.init(name: "Main", bundle: nil)
let brownVC = mainStoryboard.instantiateViewController(withIdentifier: "brownVCIdentifier") as! BrownViewController
let navigationController = application.windows[0].rootViewController as! UINavigationController
navigationController.isNavigationBarHidden = true
navigationController.pushViewController(brownVC, animated: false)
return true
}
(or)
In RedViewController(first viewController):
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let brownVC = storyboard?.instantiateViewController(withIdentifier: "brownVCIdentifier") as! BrownViewController
navigationController?.isNavigationBarHidden = true
navigationController?.pushViewController(brownVC, animated: false)
}
Github link:
https://github.com/k-sathireddy/DirectNavigationSample
You are setting the root viewcontroller as nav which has no UIView and it's creating a blank view due to which you see the black view when app is launched.
this code nav.viewControllers = [red_vc, green_vc, brown_vc] is not making any sense as you cannot set view controllers like this for UINavigationController. Navigation controller works with PUSH/POP mechanism hence you need to push the view controllers on nav controller which will correctly setup the view hierarchy. Push the controllers to brown_vc in nav and it should work.

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