How to pass data to ViewController in new storyboard - swift

I use this code for go to new story board and pass variable X to a viewController in new storyboard
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let homeViewController: UIViewController = mainStoryboard.instantiateViewController(withIdentifier: "ViewControllerCall")
homeViewController.myVar = "x"
self.present(homeViewController, animated: true, completion: nil)
But I get this error:
Value of type 'UIViewController' has no member 'myVar'

In this line:
let homeViewController: UIViewController = mainStoryboard.instantiateViewController(withIdentifier: "ViewControllerCall")
You are saying "Instantiate a view controller from the storyboard, and infer its type to be a UIViewController". However, what you need to do is specifying it as ViewControllerCall.
You can do this by type casting - adding as? ViewControllerCall. (Or as! ViewControllerCall, if you don't want to use the if let clause).
Your code should look like this:
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
if let homeViewController = mainStoryboard.instantiateViewController(withIdentifier: "ViewControllerCall") as? ViewControllerCall {
homeViewController.myVar = "x"
self.present(homeViewController, animated: true)
}
Or
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let homeViewController = mainStoryboard.instantiateViewController(withIdentifier: "ViewControllerCall") as! ViewControllerCall
homeViewController.myVar = "x"
self.present(homeViewController, animated: true)
Note that by using as! in the second way I've presented, it will crash your app if the view controller with identifier ViewControllerCall is not of type ViewControllerCall.

You have to change second line code only.
1. Go to your Main storyboard and check the class for ViewController for which you want to pass variable and set storyboard identifier same as class name.
2. Now if your class name is "ViewControllerCall" then change your line code as below:
let homeViewController = mainStoryboard.instantiateViewController(withIdentifier: "ViewControllerCall") as! ViewControllerCall

Related

Can't instantiate view controller Swift

My code worked well so far. I do not see what I could change to make it bug like that. When I want to return the user to the home page, it works, but a few seconds after the previous ViewController reappears on the screen.
I've tried to change "as! HomeViewController" with "as UIViewController" or as NavigationViewController but it keeps going to the previous ViewController.
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let balanceViewController = storyBoard.instantiateViewController(withIdentifier: "home") as! HomeViewController
self.present(balanceViewController, animated: true, completion: nil)
When I want to return the user to the home page...
You should use UINavigationController.popToViewController(_:animated:) to return to a UIViewController:
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let balanceViewController = storyBoard.instantiateViewController(withIdentifier: "home") as! HomeViewController
self.navigationController?.popToViewController(balanceViewController, animated: true)

Is it possible to make the compiler see VC name (from string) as that VC type?

I'm trying the make a function that receives a name (String) of a View Controller and then presents that View Controller modally. Example:
func presentViewControllerModally(newViewControllerName: String){
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "\(newViewControllerName)_Identifier") as! newViewControllerName
self.present(newViewController, animated: false, completion: nil)
}
But I can't make the as! newViewControllerName to work as if the newViewControllerName is the type of the newViewControllerName and not the object itself.
You don’t have to downcast controller to your custom subclass. You can just present UIViewController.
If you have to get the real viewController type in return, just use generics to do this.
func presentViewControllerModally<T: UIViewController>(newViewControllerName: String) -> T? {
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
if let newViewController = storyBoard.instantiateViewController(withIdentifier: "\(newViewControllerName)_Identifier") as? T {
self.present(newViewController, animated: false, completion: nil)
return newViewController
}
return nil
}
Then call
let myVC: MyVController = presentViewControllerModally(newViewControllerName: "MyVC")
If you don't need the right type but just UIViewController, you don't need a cast.

Do I use storyboards right?

Am I using storyboards right?
I have several storyboards with view controllers in them.
When I need to navigate between them, I do the following:
I do create a new instance of the storyboard let storyboard = ... every time I use them. Is this a bad method? Or Should I declare it in the view did load?
func detailsRequestedForMessage(message: message) {
let storyboard = UIStoryboard(name: "Additional", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "MessageDetailsViewController") as! MessageDetailsViewController
viewController.messageId = message.id
self.navigationController?.pushViewController(viewController, animated: true)
}
func viewAllMessage() {
let storyboard = UIStoryboard(name: "Additional", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "AllMessageViewController") as! AllMessageViewController
self.navigationController?.pushViewController(viewController, animated: true)
}
func viewOptions() {
let storyboard = UIStoryboard(name: "Options", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "OptionsViewController") as! OptionsViewController
self.present(viewController, animated: true)
}
It costs nothing to store a storyboard reference, but takes time to resolve a storyboard reference from a name. So I would say that you should put lines like
self.storyboardAdditional = UIStoryboard(name: "Additional", bundle: nil)
in viewDidLoad, storing the references in properties, and thereafter refer to the storyboards by way of the properties.

TabbarController child controller always return nil - Swift 4

I am trying to access the objects from child controller but it always returns nil. Please check the below code.
let mainStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let vc: UITabBarController = mainStoryboard.instantiateViewController(withIdentifier: "TabBarController") as! UITabBarController
vc.selectedIndex = 2
let vc1 = vc.viewControllers?[2] as? FormViewController //this line returns nil
vc1?.fillUserData(dataDic: convertJsonStringToDictionary(jsonString: decodedURL))
vc1?.formViewDelegate = self
self.present(vc, animated: true, completion: nil)
Please shed some light.
Based on your comments, the 3rd tab is actually a UINavigationController which has the FormViewController as its rootViewController.
Update your code as:
if let nc = vc.viewControllers?[2] as? UINavigationController, let vc1 = nc.topViewController as? FormViewController {
vc1.fillUserData(dataDic: convertJsonStringToDictionary(jsonString: decodedURL))
vc1.formViewDelegate = self
}
You can try
let nav = vc.viewControllers?[2] as? UINavigationController
let vc1 = nav?.topViewController as? FormViewController
note : you should not access any UI element here
vc1?.fillUserData(dataDic: convertJsonStringToDictionary(jsonString: decodedURL))
as it would crash the app

Presenting ViewController after resetting NSUSerDefaults

I have a reset button that resets all NSUserDeafults then it reloads to the first game of the NavigationController.
//Reset the NSUserdefault saved objects (No problems here)
let appDomain : NSString = NSBundle.mainBundle().bundleIdentifier!
NSUserDefaults.standardUserDefaults().removePersistentDomainForName(appDomain)
println("button pressed")
//Present first ViewController (Having problems in this code)
let storyboard = UIStoryboard(name: "Main", bundle: nil);
let mainViewController:ViewController = ViewController()
presentViewController(mainViewController, animated: true, completion: nil)
you have to do something like this - but i am having some problems when using this later on... sigh
I wish i knew the correct way to reset the view like this - but i can't find any info.
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
var setViewController = mainStoryboard.instantiateViewControllerWithIdentifier("GameViewController") as! UIViewController
var vc = self.view?.window?.rootViewController
vc?.presentViewController(setViewController, animated: true, completion: nil)