how can i show specific viewcontroler in notification action? - ios

how can i show specific viewcontroler in notification action?
in appdelegate
func usernotificationcenter(_center: UNUserNotification,didReceive response: UNNotificationPesponse,withCompletionHalndler completion Handler: #escaping () -> Void){
if identifer == "SHOWVIEW_ACTION":
//I want show specific viewController at this
}

func redirectToSpecificVC() {
let mainStoryboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController: UIViewController = mainStoryboard.instantiateViewController(withIdentifier: "versesVC") as UIViewController
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()}
used these function redirect to specific view controller

Add these Lines of code in did receive response, it worked for me
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let navigationController = self.window?.rootViewController as? UINavigationController
let destinationController = storyboard.instantiateViewController(withIdentifier: "YourIdentifierName") as? YourViewController
navigationController?.pushViewController(destinationController!, animated: false)
var presentedVC = self.window?.rootViewController
while (presentedVC!.presentedViewController != nil) {
presentedVC = presentedVC!.presentedViewController
}

Related

SignUp Button Not Working While Handling RootViewController?

I'm building an iOS app using a Storyboard. The root view controller is a Home View Controller. I'm creating the login/logout process, and it's mostly working fine, but I've got a few issues. I need to know the BEST way to set all this up.
When I tap on login and logout the app works fine but when I tap on Sign up Nothing works I have created a navigation controller too.
I'm just not sure what the best method is at this point.
I'm Giving you My Details
This Is MY Switcher Class For Managing View
import UIKit
class Switcher {
static func updateRootViewController() {
let status = UserDefaults.standard.bool(forKey: Constants.kUserDefaults.isSignIn)
var rootViewController : UIViewController?
#if DEBUG
print(status)
#endif
if (status == true) {
let mainStoryBoard = UIStoryboard(name: "Main", bundle: nil)
let mainTabBarController = mainStoryBoard.instantiateViewController(withIdentifier: Constants.StoryboardID.homeViewController) as! HomeViewController
rootViewController = mainTabBarController
} else {
let mainStoryBoard = UIStoryboard(name: "Main", bundle: nil)
let signInViewController = mainStoryBoard.instantiateViewController(withIdentifier: Constants.StoryboardID.signInViewController) as! SignInViewController
rootViewController = signInViewController
}
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = rootViewController
}
}
My App Delegate
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let storyBoard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
IQKeyboardManager.shared.enable = true
Switcher.updateRootViewController()
return true
}
Sign UP Button
#IBAction func signUpBtnTapped(_ sender: UIButton) {
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
guard let signUpVC = storyBoard.instantiateViewController(withIdentifier: "RegistrationViewController") as? RegistrationViewController else {
return
}
print("Register Tapped")
self.navigationController?.pushViewController(signUpVC, animated: true)
}
The issue is the your rootViewController does not have a UINavigationViewController set up, for neither of the Viewcontrollers.
what you need to do is instead of instantiating like this:
if (status == true) {
let mainStoryBoard = UIStoryboard(name: "Main", bundle: nil)
let mainTabBarController = mainStoryBoard.instantiateViewController(withIdentifier: Constants.StoryboardID.homeViewController) as! HomeViewController
rootViewController = mainTabBarController
} else {
let mainStoryBoard = UIStoryboard(name: "Main", bundle: nil)
let signInViewController = mainStoryBoard.instantiateViewController(withIdentifier: Constants.StoryboardID.signInViewController) as! SignInViewController
rootViewController = signInViewController
}
You need to instantiate a UINavigationController which it's root is these like the following
if (status == true) {
let mainStoryBoard = UIStoryboard(name: "Main", bundle: nil)
let mainTabBarController = mainStoryBoard.instantiateViewController(withIdentifier: Constants.StoryboardID.homeViewController) as! HomeViewController
let navigationController = UINavigationController(rootViewController: mainTabBarController)
rootViewController = navigationController
} else {
let mainStoryBoard = UIStoryboard(name: "Main", bundle: nil)
let signInViewController = mainStoryBoard.instantiateViewController(withIdentifier: Constants.StoryboardID.signInViewController) as! SignInViewController
let navigationController = UINavigationController(rootViewController: signInViewController)
rootViewController = navigationController
}
Now your self.navigationController?.pushViewController(signUpVC, animated: true) will work since the "navigationController" exists.

The right way to set a viewController as a root viewController

In the scenario where you have a viewController which you want to present as root view above everything else what is the right way to do this?
let Storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let MY_VIEW = Storyboard.instantiateViewControllerWithIdentifier("VIEWID")
//Is this the right way?
UIApplication.sharedApplication().delegate.window?.rootViewController?.presentViewController(MY_VIEW, animated: true, completion: nil)
//Or this?
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(MY_VIEW, animated: true, completion: nil)
In other words why would you use UIApplication.sharedApplication().delegate.window? over UIApplication.sharedApplication().keyWindow?.rootViewController? and in what scenarios? What would be the pros/cons of using one or the other?
You can do as follow.
let rootController = storyboard.instantiateViewControllerWithIdentifier("VIEWID") as! SplashVC
if self.window != nil {
self.window!.rootViewController = rootController
}
advantage of this is not getting crash when window is nil.
Another way is that(Most secure way i think)
let navigationController:UINavigationController = storyboard.instantiateInitialViewController() as! UINavigationController
let rootViewController:UIViewController = storyboard.instantiateViewControllerWithIdentifier("VIEWID") as! LoginVC
navigationController.viewControllers = [rootViewController]
self.window?.rootViewController = navigationController
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController: MainViewController = storyboard.instantiateViewControllerWithIdentifier("MainViewController") as! MainViewController
let rootViewController = self.window!.rootViewController as! UINavigationController
rootViewController.pushViewController(viewController, animated: true)

LoginViewController whose view is not in the window hierarchy! in Appldelegate

My goal is to check if there is a token in the keychain, if there isn't then simply show a login view controller screen. The problem right now, is that I get this error. I wrote this code in AppDelegate.swift
.LoginViewController: 0x7ff59b619820> on whose view is not in the window hierarchy!
Here's the code
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let keychain = Keychain(server: "https://app.herokuapp.com", protocolType: .HTTPS)
if ((try? keychain.contains("token")) != nil) {
showLoginScreen()
} else {
}
return true
}
func showLoginScreen() -> Void {
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let setViewController = mainStoryboard.instantiateViewControllerWithIdentifier("loginView") as! LoginViewController
let rootViewController = self.window!.rootViewController
rootViewController?.presentViewController(setViewController, animated: false, completion: nil)
}
try this
add self.window.makeKeyAndVisible() before present
self.window.makeKeyAndVisible()
Update
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let setViewController = mainStoryboard.instantiateViewControllerWithIdentifier("loginView") as! LoginViewController
self.window.makeKeyAndVisible()
self.window!.rootViewController.presentViewController(setViewController, animated: false, completion: nil)
for additional information see this
By setting your view controller as UINavigationControllers rootviewcontroller and then adding navigationcontroller as Windows rootviewcontrollers will work check out the modified code below:
func showLoginScreen() -> Void {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = mainStoryboard.instantiateViewControllerWithIdentifier("loginView") as UIViewController
let navigationController = UINavigationController(rootViewController: vc)
self.window!.rootViewController = navigationController
self.window!.makeKeyAndVisible()
}
If you like to switch between two viewcontrollers depending on the LoginStatus i suggest you to follow the below method:
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
if LofinStatus == true{
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = mainStoryboard.instantiateViewControllerWithIdentifier("My_Offer") as UIViewController
let navigationController = UINavigationController(rootViewController: vc)
self.window!.rootViewController = navigationController
}else{
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Login", bundle: nil)
let vc = mainStoryboard.instantiateViewControllerWithIdentifier("loginView") as UIViewController
let navigationController = UINavigationController(rootViewController: vc)
self.window!.rootViewController = navigationController
}
self.window!.makeKeyAndVisible()
NOTE: In the above code i had used two storyboards Main and Login
It worked for me perfectly,give it a try and let me know the result.Thank You

How to get Current viewcontroller (currently Presenting) using storyboard id in swift programmatically?

**How to get the presenting view controller in swift. I am using storyboard id.**And for presenting next viewcontroller how can I add to the hierarchy?
I tried like this:
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let logincontroller = mainStoryboard.instantiateViewControllerWithIdentifier("LoginViewController")
if UIApplication.sharedApplication().keyWindow?.rootViewController.presentingViewController == logincontroller {
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let nextVC = mainStoryboard.instantiateViewControllerWithIdentifier(storayboardIdentifier)
self.presentViewController(nextVC, animated: true, completion: nil)
}
In Appdelegate.swift
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
if isLoggedin == false {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyboard.instantiateViewControllerWithIdentifier("LoginViewController")
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
return true
}
else {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyboard.instantiateViewControllerWithIdentifier("HomeViewController")
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
return true
}
}
The code works, it display the view but it still have a warning
Failed to instantiate the default view controller for
UIMainStoryboardFile 'Main' - perhaps the designated entry point is
not set?
Check initial entry points.
Also to present screen below code practice is better way.
let objNextViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ID_NextViewController") as? ViewController
self.presentViewController(objNextViewController, animated: true) { () -> Void in
print("Achive")
}
EDITED :
If you want to present viewcontroller from already presented view controller then use below code.
var currentViewController : UIViewController!
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
if let viewControllers = appDelegate.window?.rootViewController?.presentedViewController
{
self.currentViewController = viewControllers as UIViewController
}
else if let viewControllers = appDelegate.window?.rootViewController?.childViewControllers
{
self.currentViewController = viewControllers.last! as UIViewController
}
let objNewViewController : NewViewController!
self.currentViewController.presentViewController(objNewViewController!, animated: true, completion: { () -> Void in
NSLog("Achived")
})
try this code for presentingViewControllerusing storyboard name:
let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("ViewController") as UIViewController
self.presentViewController(viewController, animated: false, completion: nil)
try this code,
let storyboard : UIStoryboard = UIStoryboard(name:"Main", bundle: nil)
let vc : WelcomeViewController = storyboard.instantiateViewControllerWithIdentifier("WelcomeID") as WelcomeViewController
let navigationController = UINavigationController(rootViewController: vc)
self.presentViewController(navigationController, animated: true, completion: nil)
hope its helpful
My guess is that you haven't set an initial view controller for your storyboard.
To fix this open your storyboard and select the UIViewController you want to display as the first one. Then in the Attributes inspector tab(third one from the right in the utilities panel), look under the View Controller section and make sure the Is Initial View Controller checkbox is checked.

Get Instance Of ViewController From AppDelegate In Swift

I am trying to load a specific ViewController from the app delegate in swift when a user clicks a UILocalNotification. I have figured out that this is called in this function:
func application(application: UIApplication!, didReceiveLocalNotification notification: UILocalNotification!)
But when I try and access one of the open ViewControllers I think it's returning null because my application is crashing. Here is what I am trying:
var rootViewController = self.window!.rootViewController
var storyBoard = rootViewController.storyboard
var setViewController = storyBoard.instantiateViewControllerWithIdentifier("CurrentShows") as ViewController_CurrentShows
rootViewController.navigationController.popToViewController(setViewController, animated: false)
setViewController.reloadData()
It's crashing on the popToViewController line.
You could try:
let rootViewController = self.window!.rootViewController
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let setViewController = mainStoryboard.instantiateViewControllerWithIdentifier("CurrentShows") as! DetailViewController
rootViewController?.navigationController?.popToViewController(setViewController, animated: false)
Swift 3:
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let controller = mainStoryboard.instantiateViewController(withIdentifier: "viewController")
self.present(viewController, animated: true, completion: nil)

Resources