Moving to another storyboard inside closure - ios

api.postUserLogin(Parameters: params) { (json) in
print(json)
if (json["status"].string == "true") {
self.user.id = json["data"]["id"].string
self.user.verify_status = json["data"]["verify_status"].string
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "MainViewController") as UIViewController
present(vc, animated: true, completion: nil)
}
}

Try this code:
func callViewController(){
let viewController: UIViewController = UIStoryboard(name:"STORYBOARD_NAME",bundle:nil).instantiateViewController(withIdentifier: "MainViewController")
let window :UIWindow = UIApplication.shared.keyWindow!
window.rootViewController = viewController
window.makeKeyAndVisible()
}

Related

how to present and dismiss at same time

This is my Code
#IBAction func backButton(_ sender: UIButton) {
self.dismiss(animated: true, completion: { () -> Void in
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "RequestItemPackageDetails") as! RequestItemPackageDetails
self.present(vc, animated: true, completion: nil)
})
}
this is not working only dissmising
I dont't understand your questions well. I think you want to present a new ViewController. You can use this:
UIView.animate{duration: 0.5, animations: {
(UIApplication.shared.delegate as! AppDelegate).window!.rootViewController = NextViewController()
}}
Problem is that you are dismissing self and then trying to present a new view controller on that exact same self - but at that moment self is already dismissed. You need to present that new view controller from the parent of the current view controller. I believe the best way is to setup a delegate. So the controller that you showed us and that you want to dismiss will have this:
protocol FirstDelegate: class {
func firstDismiss(_ first: First)
}
class First: UIViewController {
weak var delegate: FirstDelegate?
#IBAction func backButton(_ sender: UIButton) {
// this will tell the delegate to dismiss this contorller and present the other one
delegate?.firstDismiss(self)
}
// rest of the code omitted
}
Next, you will have to setup this in the parent that presents First view controller (here I assume that presentFirst method presents the First view controller):
class ParentViewController: UIViewController, FirstDelegate {
// rest of the code
func presentFirst() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let firstVC = storyboard.instantiateViewController(withIdentifier: "First") as! RequestItemPackageDetails
// set delegate to first:
firstVC.delegate = self
self.present(firstVC, animated: true, completion: nil)
}
func firstDismiss(_ first: First) {
first.dismiss(animated: true, completion: { () -> Void in
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "RequestItemPackageDetails") as! RequestItemPackageDetails
self.present(vc, animated: true, completion: nil)
})
}
}
Not quite sure with your Qns, but try this one out.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "RequestItemPackageDetails") as! RequestItemPackageDetails
vc.previousVC = self
self.present(vc, animated: true)
RequestItemPackageDetails.swift
var previousVC : UIViewController!
override viewDidLoad() {
previousVC.dismiss(animated: false, completion: nil)
}
You can dismiss self and then present another view from rootViewController
self.dismiss(animated: true, completion: { () -> Void in
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "RequestItemPackageDetails") as! RequestItemPackageDetails
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window!.rootViewController?.present(vc, animated: true, completion: nil)
})

Unable to Instantiate View Controller

I have a function, whereby I check if the UserDefaults are set and if not a new View Controller opens and presents a login screen which will set the user defaults.
My problem is the view controller does not Instantiate but I get a print "User not registered"
func checkUserAccount() {
let defaults = UserDefaults.standard
let accountName = defaults.bool(forKey: "PUserAccountName")
let accountPassword = defaults.bool(forKey: "PUserAccountPassword")
if accountName == true && accountPassword == true {
print("User Registered")
} else {
let storyboard: UIStoryboard = UIStoryboard(name: "PolTRiM", bundle: nil)
let vc: StudentLoginVC = storyboard.instantiateViewController(withIdentifier: "studentLogin") as! StudentLoginVC
vc.modalPresentationStyle = .custom
vc.modalTransitionStyle = .crossDissolve
self.present(vc, animated: true, completion: { _ in })
print("User not registered")
}
}
Any thoughts?
Have you double checked UIStoryBoard name and UIViewController identifier if it's written correctly? Otherwise this code is working for me
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier :"MyViewController") as! UIViewController
self.present(viewController, animated: true)

how can i show specific viewcontroler in notification action?

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
}

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)

How to Navigate from one View Controller to another using Swift

I'd like to navigate from one view controller to another. How can I convert the following Objective-C code into Swift?
UIViewController *viewController = [[self storyboard] instantiateViewControllerWithIdentifier:#"Identifier"];
UINavigationController *navi = [[UINavigationController alloc] initWithRootViewController:viewController];
[self.navigationController pushViewController:navi animated:YES];
Create a swift file (SecondViewController.swift) for the second view controller
and in the appropriate function type this:
let secondViewController = self.storyboard.instantiateViewControllerWithIdentifier("SecondViewController") as SecondViewController
self.navigationController.pushViewController(secondViewController, animated: true)
Swift 2+
let mapViewControllerObj = self.storyboard?.instantiateViewControllerWithIdentifier("MapViewControllerIdentifier") as? MapViewController
self.navigationController?.pushViewController(mapViewControllerObj!, animated: true)
Swift 4
let vc = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "IKDetailVC") as? IKDetailVC
self.navigationController?.pushViewController(vc!, animated: true)
In my experience navigationController was nil so I changed my code to this:
let next = self.storyboard?.instantiateViewControllerWithIdentifier("DashboardController") as! DashboardController
self.presentViewController(next, animated: true, completion: nil)
Don't forget to set ViewController StoryBoard Id in StoryBoard -> identity inspector
If you don't want the back button to appear (which was my case, because I wanted to present after a user logged in) here is how to set the root of the nav controller:
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("YourViewController") as! YourViewController
let navigationController = UINavigationController(rootViewController: vc)
self.presentViewController(navigationController, animated: true, completion: nil)
SWIFT 3.01
let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "Conversation_VC") as! Conversation_VC
self.navigationController?.pushViewController(secondViewController, animated: true)
In swift 4.0
var viewController: UIViewController? = storyboard().instantiateViewController(withIdentifier: "Identifier")
var navi = UINavigationController(rootViewController: viewController!)
navigationController?.pushViewController(navi, animated: true)
In Swift 4.1 and Xcode 10
Here AddFileViewController is second view controller.
Storyboard id is AFVC
let next = self.storyboard?.instantiateViewController(withIdentifier: "AFVC") as! AddFileViewController
self.present(next, animated: true, completion: nil)
//OR
//If your VC is DashboardViewController
let dashboard = self.storyboard?.instantiateViewController(withIdentifier: "DBVC") as! DashboardViewController
self.navigationController?.pushViewController(dashboard, animated: true)
If required use thread.
Ex:
DispatchQueue.main.async {
let next = self.storyboard?.instantiateViewController(withIdentifier: "AFVC") as! AddFileViewController
self.present(next, animated: true, completion: nil)
}
If you want move after some time.
EX:
//To call or execute function after some time(After 5 sec)
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
let next = self.storyboard?.instantiateViewController(withIdentifier: "AFVC") as! AddFileViewController
self.present(next, animated: true, completion: nil)
}
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let home = storyBoard.instantiateViewController(withIdentifier: "HOMEVC") as! HOMEVC
navigationController?.pushViewController(home, animated: true);
Swift 3
let secondviewController:UIViewController = self.storyboard?.instantiateViewController(withIdentifier: "StoryboardIdOfsecondviewController") as? SecondViewController
self.navigationController?.pushViewController(secondviewController, animated: true)
In swift 3
let nextVC = self.storyboard?.instantiateViewController(withIdentifier: "NextViewController") as! NextViewController
self.navigationController?.pushViewController(nextVC, animated: true)
let objViewController = self.storyboard?.instantiateViewController(withIdentifier: "ViewController") as! ViewController
self.navigationController?.pushViewController(objViewController, animated: true)
Swift 5
Use Segue to perform navigation from one View Controller to another View Controller:
performSegue(withIdentifier: "idView", sender: self)
This works on Xcode 10.2.
Swift 4
You can switch the screen by pushing navigation controller first of all you have to set the navigation controller with UIViewController
let vc = self.storyboard?.instantiateViewController(withIdentifier: "YourStoryboardID") as! swiftClassName
self.navigationController?.pushViewController(vc, animated: true)
In AppDelegate you can write like this...
var window: UIWindow?
fileprivate let navigationCtrl = UINavigationController()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
self.createWindow()
self.showLoginVC()
return true
}
func createWindow() {
let screenSize = UIScreen.main.bounds
self.window = UIWindow(frame: screenSize)
self.window?.backgroundColor = UIColor.white
self.window?.makeKeyAndVisible()
self.window?.rootViewController = navigationCtrl
}
func showLoginVC() {
let storyboardBundle = Bundle.main
// let storyboardBundle = Bundle(for: ClassName.self) // if you are not using main application, means may be you are crating a framework or library you can use this statement instead
let storyboard = UIStoryboard(name: "LoginVC", bundle: storyboardBundle)
let loginVC = storyboard.instantiateViewController(withIdentifier: "LoginVC") as! LoginVC
navigationCtrl.pushViewController(loginVC, animated: false)
}
For Swift 4 & 5 Users can use this way
Swift 5
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyBoard.instantiateViewController(withIdentifier: "YourViewController") as! YourViewController
self.navigationController?.pushViewController(vc, animated: true)
Swift 4
let vc = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "YourViewController") as? YourViewController
self.navigationController?.pushViewController(vc!, animated: true)
Better practices Swift 5.0
More reusable and readable
Create a protocol
protocol Storyboarded { }
Now create an extension of the protocol
extension Storyboarded where Self: UIViewController {
static func instantiateFromMain() -> Self {
let storyboardIdentifier = String(describing: self)
// `Main` can be your stroyboard name.
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
guard let vc = storyboard.instantiateViewController(withIdentifier: storyboardIdentifier) as? Self else {
fatalError("No storyboard with this identifier ")
}
return vc
}
}
// Make a ViewController extension to use on all of your ViewControllers
extension UIViewController: Storyboarded {}
How to use
let vc = MyViewController.instantiateFromMain()
//here you can pass any data to the next view controller. for example we have a variable with name `myString` in our next view contoller and we want to pass the data my `self viewController`
vc.myString = "This string passed by MyViewController"
self.navigationController?.pushViewController(vc, animated: true)
Note:- You need to give the same identifier on the storyboard as your UIViewController class has. Check the example below
Update for Swift 5:
let next = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
self.present(next, animated: true, completion: nil)
Don't forget to update the Storyboard ID for both View Controllers!

Resources