Swift UIBarButtonItem is hidden but works - ios

I have an problem with an UIBarButtonItem. If I protect my app with an ViewController, to authenticate the User through Touch ID, then the UIBarButtonItem in the Navigation Controller is hidden.
The code in the AppDelegate:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let touchIDonoff = UserDefaults.standard.object(forKey: "touchIDActive") as! Bool!
if touchIDonoff == true {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let loginVC = storyboard.instantiateViewController(withIdentifier: "TouchIDViewController") as! TouchIDViewController
self.window?.rootViewController = loginVC
}
return true
}
Code in the ViewController for TouchID-Request:
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.async {
self.touchIDrequest()
}
#IBAction func buttonTouchID(_ sender: AnyObject) {
touchIDabfrage()
}
func touchIDrequest() {
let authenticationContext = LAContext()
var error: NSError?
if authenticationContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
authenticationContext.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "Please authenticate", reply: { (success: Bool, error: Error?) in
if success {
self.navigatetoAuthenticatedVC()
} else {
if let evaluateError = error as? NSError {
print(error)
/*let message = self.errorMessageForLAErrorCode(errorCode: evaluateError.code)
self.showAlertViewAfterEvaluatingPolicyWithMessage(message: message)
*/
}
}
})
} else {
showAlertViewForNoBiometrics()
return
}
}
func navigatetoAuthenticatedVC() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let tabBarController = storyboard.instantiateViewController(withIdentifier: "LoggedInVC") as! UITabBarController
let appDelegate = UIApplication.shared.delegate as! AppDelegate
DispatchQueue.main.async {
appDelegate.window?.rootViewController = tabBarController
}
}
If I hit the hidden UIBarButtonItem it works and bring me to the next ViewController and when I go back, the UIBarButtonItem is visible.
What did I wrong? Any help please?
Best regards

Related

Once i Login why i am not getting HomeViewController as Rootviewcontroller in Swift?

In appdelegate i am getting UserId.. means i am login but when i run second time i am not getting homeviewcontroller as rootviewcontroller why? still it shows phonenumviewcontroller
navigationcontroller -> phonenumviewcontroller -> registrationiewcontroller -> homeviewcontroller
In storyboard navigationcontroller is initialviewcontroller
In registrationviewcontroller i am getting userId which i have saved in keychain.
I dont have signout button so i have written code like below in registrationiewcontroller
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String:AnyObject]
print("terms and condition JSON \(json)")
let jsonObj: String = json["Success"] as? String ?? ""
if jsonObj == "true" {
let userID: String=jsonObj?["userId"] as? String ?? ""
DispatchQueue.main.async {
KeychainWrapper.standard.set(userID, forKey: "USERID")
let viewController = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController;
UserDefaults.standard.set("NoLogout", forKey:"Signout")
self.navigationController?.pushViewController(viewController, animated: true);
}
}
}
no signout button so added this code in registrationviewcontroller
UserDefaults.standard.set("NoLogout", forKey:"Signout")
this code in appdelegate: getting userId but still homeviewcontroller is not coming as rootviewcontroller, only phonenumviewcontroller is coming why?
var savedUserId: String?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
savedUserId = KeychainWrapper.standard.string(forKey: "USERID")
KeychainWrapper.standard.set(savedUserId ?? "", forKey: "PersonalID")
print("appdelegate userid \(savedUserId)")
logOutString = UserDefaults.standard.string(forKey: "Signout") as NSString? ?? "" as NSString
if logOutString.isEqual(to: "NoLogout") {
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyBoard = UIStoryboard.init(name: "Main", bundle: nil)
let viewcontroller = storyBoard.instantiateViewController(withIdentifier: "HomeViewController")
let navigationController = UINavigationController(rootViewController: viewcontroller)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
}
else {
}
return true
}
once registration is completed i need rootviewcontroller as homeviewcontroller... how to get that, please help me with code
From whatever I've gathered, here's what you need to do:
In AppDelegate:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let isUserLoggedIn = UserDefaults.standard.bool(forKey: "isUserLoggedIn") // Give you own check to see if user is logged in
window = UIWindow()
window?.makeKeyAndVisible()
let viewController = isUserLoggedIn ? MainViewController() : LoginViewController()
window?.rootViewController = UINavigationController(rootViewController: viewController)
return true
}
}
class MainViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Logout", style: .plain, target: self, action: #selector(handleUserLoggedOut))
}
#objc func handleUserLoggedOut() {
UserDefaults.standard.set(false, forKey: "isUserLoggedIn")
UIApplication.shared.keyWindow?.rootViewController = UINavigationController(rootViewController: LoginViewController())
}
}
class LoginViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Login", style: .plain, target: self, action: #selector(handleUserLoggedIn))
}
#objc func handleUserLoggedIn() {
UserDefaults.standard.set(true, forKey: "isUserLoggedIn")
UIApplication.shared.keyWindow?.rootViewController = UINavigationController(rootViewController: MainViewController())
}
}
This is only a skeleton. Give both controller different background colours and button action to call handleUserLoginIn and handleUserLoggedOut on respective controllers and see how it works. Play around with it and figure out.
Note: keyWindow is deprecated so you need to use this instead at all places.
let keyWindow = UIApplication.shared.connectedScenes
.filter({$0.activationState == .foregroundActive})
.map({$0 as? UIWindowScene})
.compactMap({$0})
.first?.windows
.filter({$0.isKeyWindow}).first
Edit: I've also added the login, logout buttons and set backgroundColors for you to see for yourself the result.

Presenting different UIViewController on the app Launch

I need to present different UIViewController on the launch of my app. I have a "login" page for the user to interact with. Once the user logs in or creates an account it takes to a different UIViewController with a map to interact with. I've looked online and so far I know that we should do it within AppDelegate.swift file. I have not completed the statement whether or not the user has logged in since I am still running into some errors
AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Thread.sleep(forTimeInterval: 2.0)
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
window?.rootViewController = MainNavigationContoller()
return true
}
I also have another swift file with MainNavigationContoller that should call the mainviewController
override func viewDidLoad() {
super.viewDidLoad()
let isloggedIn = false
if isloggedIn == false {
self.present(mainViewController(), animated: true, completion: nil)
} else {
self.present(mapViewController(), animated: true, completion: nil)
}
}
The app launches with the launchScreen but then sends errors to mainViewController such as Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
You are not instantiating the View Controllers properly.
Here is a function that I use to make a root view controller, put this into your AppDelegate.
func makeRootVC(storyBoardName : String, vcName : String) {
let vc = UIStoryboard(name: storyBoardName, bundle: Bundle.main).instantiateViewController(withIdentifier: vcName)
let nav = UINavigationController(rootViewController: vc)
nav.navigationBar.isHidden = true
self.window?.rootViewController = nav
let options: UIView.AnimationOptions = .transitionCrossDissolve
let duration: TimeInterval = 0.6
UIView.transition(with: self.window!, duration: duration, options: options, animations: {}, completion: nil)
}
Now in your Appdelegate, replace your code with this:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Thread.sleep(forTimeInterval: 2.0)
self.makeRootVC(storyboardName: "Main", vcName : "YourVCStoryboardId")
return true
}
and in your MainNavigationController,
override func viewDidLoad() {
super.viewDidLoad()
let isloggedIn = false
let appDelegateObj = UIApplication.shared.delegate as! AppDelegate
if isloggedIn == false {
appDelegateObj.makeRootVC(storyboardName: "Main", vcName: "mainViewController")
} else {
appDelegateObj.makeRootVC(storyboardName: "Main", vcName: "mapViewController")
}
}
NOTE: Open storyboard and give every controller a StoryboardID. What I prefer is naming them the same as ViewController's name as it is easy to remember. and in vcName, we need to pass the storyboarID of the controller we want to present.
UPDATE:
Above code is for making a root view controller, if you want to push controllers, you can use this code instead:
extension UIViewController {
func pushVC(storyboardName : String, vcname : String) {
let vc = UIStoryboard.init(name: storyboardName, bundle: Bundle.main).instantiateViewController(withIdentifier: vcname)
vc.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(vc, animated: true)
}
}
In your MainNavigationController if instead of making root view controllers in viewDidLoad, you want to just push the controller, then use the above code like this:
override func viewDidLoad() {
super.viewDidLoad()
let isloggedIn = false
if isloggedIn == false {
self.pushVC(storyboardName: "Main", vcName: "mainViewController")
} else {
self.pushVC(storyboardName: "Main", vcName: "mapViewController")
}
}

Back button disappears after creating AppDelegate in Swift 3.0

I created the structure as below in xcode 8 swift 3.0.
Before I add AppDelegate code. Back button still appear fine on Apply, Apply Behalf and Profile controller.
I use segue to open page.
But after I add AppDelegate code into Homepage and Login controllers , back button disappears on Apply, Apply behalf and profile controller page.
Can someone help or explain why is this happening ? How to enable back the back button on apply, apply behalf and profile page ?
Thanks.
Home.swift
import UIKit
class ViewController: UIViewController {
#IBOutlet var staffNumberLbl: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
staffNumberLbl.text = UserDefaults.standard.object(forKey: "login") as? String
}
override func viewDidAppear(_ animated: Bool) {
let isUserLoggedIn = UserDefaults.standard.bool(forKey: "loggedIn")
if(!isUserLoggedIn){
self.performSegue(withIdentifier: "loginview", sender: self)
}
}
#IBAction func logoutData(_ sender: Any) {
UserDefaults.standard.set(false, forKey: "loggedIn")
UserDefaults.standard.synchronize();
let loginViewController = self.storyboard!.instantiateViewController(withIdentifier: "loginview") as! LoginViewController
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = loginViewController
appDelegate.window?.makeKeyAndVisible()
}
}
Login.swift
import UIKit
class LoginViewController: UIViewController {
#IBOutlet var loginlbl: UITextField!
#IBOutlet var passlbl: UITextField!
#IBOutlet var login_button: UIButton!
var login: String!
var pw: String!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func loginData(_ sender: Any) {
login = loginLbl.text
pw = passLbl.text
if(login == "" || pw == ""){
return
}
else{
let url = URL(string: "http://localhost/login.php")
let session = URLSession.shared
let request = NSMutableURLRequest(url: url! as URL)
request.httpMethod = "POST"
let LoginDataToPost = "login=\(login!)&pw=\(pw!)"
request.httpBody = LoginDataToPost.data(using: String.Encoding.utf8)
let task = session.dataTask(with: request as URLRequest, completionHandler: {
(data, response, error) in
if error != nil {
return
}
else {
do {
if let json = try JSONSerialization.jsonObject(with: data!) as? [String: String]
{
DispatchQueue.main.async
{
let message = Int(json["message"]!)
let login = json["login"]
if(message == 1) {
UserDefaults.standard.set(true, forKey: "isUserLoggedIn")
UserDefaults.standard.set(login, forKey: "login")
UserDefaults.standard.synchronize();
self.dismiss(animated: true, completion: nil)
let myViewController:ViewController = self.storyboard!.instantiateViewController(withIdentifier: "ViewController") as! ViewController
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = myViewController
appDelegate.window?.makeKeyAndVisible()
print("Value for login is : \(login!)")
return
}
else {}
}
}
else {}
}
catch let jsonParse {}
}
})
task.resume()
}
}
}
AppDelegate.swift
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let mainStoryBoard: UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let isUserLoggedIn:Bool = UserDefaults.standard.bool(forKey: "isUserLoggedIn")
if(!isUserLoggedIn) {
let loginViewController = mainStoryBoard.instantiateViewController(withIdentifier: "loginview") as! LoginViewController
window!.rootViewController = loginViewController
window!.makeKeyAndVisible()
}
else {
let homePage = mainStoryBoard.instantiateViewController(withIdentifier: "ViewController") as! ViewController
window!.rootViewController = homePage
window!.makeKeyAndVisible()
}
return true
}
}
You are setting rootviewcontroller without embedding navigation controller to it in logoutData & loginData function.
Use this code :
let navigationController = UINavigationController.init(rootViewController: myViewController)
appDelegate.window?.rootViewController = navigationController
Use this code in AppDelegate:
if(!isUserLoggedIn) {
let loginViewController = mainStoryBoard.instantiateViewController(withIdentifier: "loginview") as! LoginViewController
let navigationController = UINavigationController.init(rootViewController: loginViewController)
appDelegate.window?.rootViewController = navigationController
window!.makeKeyAndVisible()
}
else {
let homePage = mainStoryBoard.instantiateViewController(withIdentifier: "ViewController") as! ViewController
let navigationController = UINavigationController.init(rootViewController: homePage)
appDelegate.window?.rootViewController = navigationController
window!.makeKeyAndVisible()
}
Remove this from Home.swift,
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = loginViewController
appDelegate.window?.makeKeyAndVisible()
because its not inheriting the properties of Navigation controller
and add it in Appdelegate.swift file
For the other 3 viewcontrollers, you need to add the Navigation controller between eachSegway in order to inherit it or code the button by instantiating the viewcontrollers respectively
After successful login,try to make NavigationController as rootViewController instead of your ViewController
Your back button will start appearing.
In AppDelegate, in else block, instead of this line
let homePage = mainStoryBoard.instantiateViewController(withIdentifier: "ViewController") as! ViewController
write this
let homePage = mainStoryBoard.instantiateViewController(withIdentifier: "NavigationController") as! UINavigationController
Inside LoginViewController, in the block if(message == 1)
replace
let myViewController:ViewController = self.storyboard!.instantiateViewController(withIdentifier: "ViewController") as! ViewController
with
let navController:UINavigationController = self.storyboard!.instantiateViewController(withIdentifier: "NavigationController") as! UINavigationController
Also set storyboard identifier for UINavigationController in storyboard to NavigationController
Depending on your configuration:
self.navigationItem.hidesBackButton = YES;
OR:
self.navigationController.navigationItem.hidesBackButton = YES;
Or, if you just want to disable the button without hiding it, you can use this.
self.navigationController.navigationItem.backBarButtonItem.enabled = NO;

Why is this variable not printing in this function?

When ViewController loads, the correct value gets printed. But when tried to print the same value with a UIButton, the print is nil
ViewController
var userEmail: String?
func userLoggedIn(data: String) {
userEmail = data //sent from delagate
print(userEmail) // successfully printed
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "loginView" {
let loginViewController: LoginViewController = segue.destination as! LoginViewController
loginViewController.delegate = self
}
}
override func viewDidAppear(_ animated: Bool) {
let isUserLoggedIn = UserDefaults.bool(UserDefaults.standard)(forKey: "isUserLoggedIn")
if(!isUserLoggedIn) {
self.performSegue(withIdentifier: "loginView", sender: self);
}
}
#IBAction func createCommunityTapped(_ sender: AnyObject) {
let createCommunityController = self.storyboard?.instantiateViewController(withIdentifier: "CreateNewCommunity") as! CreateNewCommunity
print ("now here ", userEmail) // prints nil
createCommunityController.myEmail = userEmail
}
The userEmail value is being passed from LoginViewController via this section of code:
if(returnValue != "error") {
self.delegate?.userLoggedIn(data: userEmail! )
UserDefaults.set(UserDefaults.standard)(true, forKey: "isUserLoggedIn");
let mainPage = self.storyboard?.instantiateViewController(withIdentifier: "ViewController")
let mainPageNav = UINavigationController(rootViewController: mainPage!)
let appDelegate = UIApplication.shared.delegate
appDelegate?.window??.rootViewController = mainPageNav
self.dismiss(animated: true, completion: nil)
}
AppDelegate:
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let isUserLoggedIn = UserDefaults.bool(UserDefaults.standard)(forKey: "isUserLoggedIn")
if(!isUserLoggedIn) {
let loginViewController = mainStoryboard.instantiateViewController(withIdentifier: "LoginViewController")
self.window?.rootViewController = loginViewController
window!.makeKeyAndVisible()
} else {
let protectedPage = mainStoryboard.instantiateViewController(withIdentifier: "ViewController")
self.window?.rootViewController = protectedPage
window!.makeKeyAndVisible()
}
return true
}
The issue seems to lie in your Login view controller. You're passing the userEmail to your first instance of ViewController, then creating a new instance of ViewController and setting it as the root, which releases the first one. The first step should be to remove this code:
let mainPage = self.storyboard?.instantiateViewController(withIdentifier: "ViewController")
let mainPageNav = UINavigationController(rootViewController: mainPage!)
let appDelegate = UIApplication.shared.delegate
appDelegate?.window??.rootViewController = mainPageNav
In your AppDelegate, you should set the root view controller to ViewController, and modally present the LoginViewController on top of it if the user is not logged in. Make sure to set the LoginViewController's delegate to ViewController. Then your login logic can be:
if(returnValue != "error") {
self.delegate?.userLoggedIn(data: userEmail!)
UserDefaults.standard.set(true, forKey: "isUserLoggedIn")
self.dismiss(animated: true, completion: nil)
}

Value of type 'AppDelegate' has no member 'window'

Im trying to use the 3D touch Quick Actions and I'm setting it up copying VEA Software code. In his sample code it works perfectly but when I try to add it to my app I get some unusual errors. I am new to coding and swift so please explain as much as possible. Thanks. Below I have the code which is in my app delegate.
This is where I'm getting the error (self.window?):
#available(iOS 9.0, *)
func handleShortcutItem(shortcutItem: UIApplicationShortcutItem) -> Bool
{
var handled = false
var window: UIWindow?
guard ShortcutIdentifier(fullType: shortcutItem.type) != nil else { return false }
guard let shortcutType = shortcutItem.type as String? else { return false }
switch (shortcutType)
{
case ShortcutIdentifier.First.type:
handled = true
var window = UIWindow?()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let navVC = storyboard.instantiateViewControllerWithIdentifier("ProjectPage") as! UINavigationController
// Error on line below
self.window?.rootViewController?.presentViewController(navVC, animated: true, completion: nil)
break
case ShortcutIdentifier.Second.type:
handled = true
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let navVC = storyboard.instantiateViewControllerWithIdentifier("ContactPageView") as! UINavigationController
// Error on line below
self.window?.rootViewController?.presentViewController(navVC, animated: true, completion: nil)
break
case ShortcutIdentifier.Third.type:
handled = true
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let navVC = storyboard.instantiateViewControllerWithIdentifier("ViewController") as! UINavigationController
// Error on line below
self.window?.rootViewController?.presentViewController(navVC, animated: true, completion: nil)
break
default:
break
}
return handled
}
Xcode 12.0 Swift 5.0
At the moment you need to:
Remove the “Application Scene Manifest” from info.plist file;
Remove scene delegate class;
Remove scene related methods in AppDelegate class;
If missing, add the property var window: UIWindow? to your AppDelegate class.
Add some logic in func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?).
Example of implementation when you need to support iOS 12 and 13:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
configureInitialViewController()
return true
}
private func configureInitialViewController() {
let initialViewController: UIViewController
let storyboard = UIStoryboard(name: "Main", bundle: nil)
window = UIWindow()
if (condition) {
let mainViewController = storyboard.instantiateViewController(withIdentifier: "mainForm")
initialViewController = mainViewController
} else {
let loginViewController = storyboard.instantiateViewController(withIdentifier: "loginForm")
initialViewController = loginViewController
}
window?.rootViewController = initialViewController
window?.makeKeyAndVisible()
}
}
In iOS 13, Xcode 11, the sceneDelegate handles the functionality of UIScene and window. The window performs properly when used in the sceneDelegate.
When you are using Scene view then windows object is in the scene delegate. Copy window object and place it in the app delegate and it will work.
if your project already has SceneDelegate file ,then you need to use it insead of AppDelegate , like this way :
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let _ = (scene as? UIWindowScene) else { return }
let mainStoryBoard = UIStoryboard(name: "Main", bundle: nil)
let viewController = mainStoryBoard.instantiateViewController(withIdentifier: "setCountry")
window?.rootViewController = viewController
}
Sometimes when you have an issue in AppDelegate it can be solved with a quick Product -> Clean. Hope this helps.
This worked for me.
Add the following code inside SceneDelegate's first function's, func scene(...), if statement, if let windowScene = scene as? UIWindowScene {..Add Below Code Here..}.
Make sure to add import MediaPlayer at the top of the file.
let volumeView = MPVolumeView()
volumeView.alpha = 0.000001
window.addSubview(volumeView)
At the end your code should be:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Create the SwiftUI view that provides the window contents.
let contentView = ContentView()
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
// MARK: Hide Volume HUD View
let volumeView = MPVolumeView()
volumeView.alpha = 0.000001
window.addSubview(volumeView)
}
}
first you need to specify which shortcut you need to use , cuz there are two types of shortcuts : dynamic and static and let say that you choose the static that can be done and added from the property list info then you have to handle the actions for each shortcut in the app delegate file in your project
func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: #escaping (Bool) -> Void) {
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let mainTabController = storyboard.instantiateViewController(withIdentifier: "Tab_Bar") as? Tab_Bar
let loginViewController = storyboard.instantiateViewController(withIdentifier: "LoginVC") as? LoginVC
let doctor = storyboard.instantiateViewController(withIdentifier: "DrTabController") as! DrTabController
getData(key: "token") { (token) in
getData(key: "type") { (type) in
if token != "" && type != "" , type == "2" {
self.window?.rootViewController = mainTabController
if #available(iOS 13.0, *) {
self.window?.overrideUserInterfaceStyle = .light
} else {
self.window?.makeKeyAndVisible()
}
if shortcutItem.type == "appointMent" {
mainTabController?.selectedIndex = 1
} else if shortcutItem.type == "Chatting" {
mainTabController?.selectedIndex = 2
}
} else if token != "" && type != "" , type == "1"{
self.window?.rootViewController = doctor
if #available(iOS 13.0, *) {
self.window?.overrideUserInterfaceStyle = .light
} else {
self.window?.makeKeyAndVisible()
}
if shortcutItem.type == "appointMent" {
mainTabController?.selectedIndex = 1
} else if shortcutItem.type == "Chatting" {
mainTabController?.selectedIndex = 2
}
} else if token == "" && type == "" {
self.window?.rootViewController = loginViewController
if #available(iOS 13.0, *) {
self.window?.overrideUserInterfaceStyle = .light
} else {
self.window?.makeKeyAndVisible()
}
if shortcutItem.type == "appointMent" {
mainTabController?.selectedIndex = 1
} else if shortcutItem.type == "Chatting" {
mainTabController?.selectedIndex = 2
}
}
}
}
}
this will be work so fine for you but first you have to determine the rootViewController we can say like :
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
self.window?.rootViewController = mainTabController
if #available(iOS 13.0, *) {
self.window?.overrideUserInterfaceStyle = .light
} else {
self.window?.makeKeyAndVisible()
}
if shortcutItem.type == "appointMent" {
mainTabController?.selectedIndex = 1
} else if shortcutItem.type == "Chatting" {
mainTabController?.selectedIndex = 2
}

Resources