I'm using storyboard.instantiateViewController to start a TableViewController, but when I try to downcast it, I get an error:
Could not cast value of type 'UITableViewController' (0x109b30de8) to 'PresenceTableViewController' (0x1060329f0).
My class PresenceTableViewController is a subclass of UITableViewController, and the storyboard has assigned the VC class correctly.
So why would this fail?
presenceViewController = storyboard.instantiateViewController(withIdentifier: "userPresenceTable") as! PresenceTableViewController
I tried the possible cases for "Could not cast value..." and it was woking fine for all cases, and then I generated this error in one case when module was not inherited from target. This solved the problem for me.
Just re-enter the class type on storyboard, it will automatically select "Inherit module from target". This would solve your problem.
Also make sure that your controller from you want to use must be embed with navigation bar
let tableviewController = self.storyboard?.instantiateViewController(withIdentifier: "tableviewController") as! tableviewController
self.navigationController?.pushViewController(tableviewController, animated: true)
Related
Today I split my storyboards and now I'm getting an error and I don't know how to fix it.
I have 1 storyboard (Products) which contains all my UIViewControllers from first Tab and I have another storyboard (Cart) which contains all my UIViewControllers from the second tab.
I've set the StoryBoard Entry Point to all navigations controller, I set references in the MainStoryboard, I set the correct storyboard destination for each StoryBoard Reference, I really don't know what I did wrong.
Here is the error which I get it when I launch the app:
"Could not cast value of type 'ShoppingLand.CartViewController' (0x10d72a780) to 'ShoppingLand.ProductsViewController' (0x10d72a8c0)."
Here is my function where is crashing (is crashing on first line):
// Append the selectedProducts into productsInCartArray using the TabBarController
func fetchSelectedProducts() {
let firstTabVC = ((self.tabBarController?.viewControllers![0] as! UINavigationController).viewControllers[0] as! ProductsViewController)
productsInCartArray = firstTabVC.selectedProductsArray
productPricesArray = firstTabVC.priceForSelectedProductsArray
getProductsPhotosArray = firstTabVC.googlePhotosArray
totalSum = productPricesArray.reduce(0, +)
}
Here is a picture with my StoryBoards:
Thank you for your time !
I fixed this error in a second after I swapped this 2 icons using drag and drop.
Thank you for your time !
I have the following code which is intended to change views. This code is executed when my 'UITableViewRowAction' is selected and is intended to navigate to a different UITableViewController. However, I am getting the error below and I do not understand what I am doing incorrectly.
let storyBoard: UIStoryboard = UIStoryboard.init(name: "Main", bundle: nil)
let selectFolderViewController = storyBoard.instantiateViewController(withIdentifier: "SaveArticleTableViewController") as! SaveArticleTableViewController
self.navigationController?.pushViewController(selectFolderViewController, animated: true)
The error that i am getting in the console is:
Could not cast value of type 'UINavigationController' (0x106f5c898) to 'lifesci_PubMed.SaveArticleTableViewController' (0x104dbb658).
All my ViewControllers are embedded within a Navigation Controller
It's very likely that you have not properly set the custom class of the view controller in Storyboard. Here's an image ...
You would type "SaveArticleTableViewController" in that slot.
It's quite possible you have other problem as well, but that will get you going.
The error is actually quite descriptive here:
Could not cast value of type 'UINavigationController' to 'SaveArticleTableViewController'
At first I thought that this was because your view controller SaveArticleTableViewController is not actually set with a custom class. If you're using Interface Builder, make sure you've set the class type in the view controller's property inspector:
If you're doing it in code, make sure your custom class is inheriting properly.
But taking a leap of a guess, your target is "UINavigationController", but your custom class name that it's trying to cast to suggests that your target is a table view "SaveArticleTableViewController". Moreover, I'd bet that this is the tableview that is the source not the destination. I'd double check that you're actually instantiating the right view controller - typically you'd name this something like "SaveArticleDetailViewController", or guessing by your code, maybe it's "SelectFolderViewController", but that's up to you.
For example:
let storyBoard: UIStoryboard = UIStoryboard.init(name: "Main", bundle: nil)
let selectFolderViewController = storyBoard.instantiateViewController(withIdentifier: "SelectFolderViewController") as! SelectFolderViewController
self.navigationController?.pushViewController(selectFolderViewController, animated: true)
This also requires that you set self.navigationController to the containing nav controller.
I am new developer and I am struggling with my Walkthrough screen for my application.
I have created it, but when I click continue to my main screen, the app crashes.
Here is the code I have under my "continue" button:
#IBAction func skipButtonTapped(_ sender: AnyObject) {
let nextView: FirstViewController = self.storyboard?.instantiateViewController(withIdentifier: "FirstViewController") as! FirstViewController
let appdelegate = UIApplication.shared.delegate as! AppDelegate
appdelegate.window!.rootViewController = nextView
}
and the error I get is :
Could not cast value of type 'UITabBarController' (0x19f33c0d8) to 'Iwin.FirstViewController' (0x100057220).
I think the Problem is in the name of the name of the identifier which in my case is "FirstViewController"
This is the storyboard ID of my TabBarController, which should be the first screen of my app.
Attached I have uploaded a picture too.
The error you are seeing probably has to do with the forced conversion (as!) you do on the first line of the function. You're doing the following:
Calling instantiateViewController(withIdentifier:), which Apple API Documentation says returns UIViewController (in this case, it's returning UITabBarController, a subclass)
Force converting a UITabBarController to a FirstViewController, which fails.
This is because forced conversion guarantees that the resulting value won't be nil, but it doesn't guarantee that it won't fail (crash). UITabBarController is simply not convertible, because it does not extend/implement FirstViewController.
My guess is that even though you've given that view controller the identifier "FirstViewController", but it's just a regular old UITabBarController. Double check in Interface Builder that this View Controller is actually an instance of your FirstViewController class.
Looking at your photo, the "Class" field has the default value of UITabBarController -- this should be the first thing you try to change. Fill in FirstViewController, and let me know if it works.
I have a UIViewController that I have had in a storyboard for a while with no problems. As my application grew, and I was using that view controller in more and more places, I realized that I should probably make it more portable, rather than have so many segues to it from hither and yon across the board. I've done splits like this before, so I did what I figured was logical here. I selected that view controller, cut it, and pasted into an empty .xib file. After changing each call to performSegueWithIdentifier to an init(nibName:bundle:) and presentViewController, I get a crash, with an object found unexpectedly nil in viewDidLoad()...
I set the value of this object after each init(...) call, just before presenting the view controller. The nil object is called from viewDidLoad(). This is a problem. I just set this, and now it's gone?!
I overrode the init(...) method, and found that self in init(nibName:bundle:) doesn't have the same memory address as self in viewDidLoad(). Also strange.
I overrode the other init() methods, and found that, after I call to present my view, my object is being instantiated again via init(coder:)! The self in here happens to be the exact self where my property is found nil!
The only reason I see for init(coder:) to be called at all is that I am loading my view from a .xib, but I thought this was handled in init(nibNamed:bundle:)? According to the docs, I do indeed get a call to init(coder:) if I'm loading from a storyboard, and doesn't touch the former... It also says that the nib isn't loaded until the controller's view is queried. If I understand it correctly, my view shouldn't get queried until I present the view. As the crash happens only when I present it, the issue likely stems from that.
I'm stuck here. I still need to get this contextual information to the view controller before it's presented. I've even tried making a proxy class to do the instantiating and property setting before presentation, but I still can't shake this second instance! I get one from init(nibName:bundle:), and another from init(coder:). Neither gets presented, and the latter gives me a nil object error. Any help at all in understanding why this is, and how I might work around this bug (feature?) would be much appreciated. Thank you!
Update:
On a whim, I decided to paste the view controller back into the storyboard, separate from the main hierarchy, and try instantiating it by its identifier. It worked! Not entirely sure how, but by George it worked! Now my question is this: Why?? What is so terribly evil and taboo about .xibs that Xcode and iOS won't tell me? I'm not a little flummoxed by this behavior. I'll keep trying with the .xib, if only to keep Xcode from yelling at me about entrance points...
I don't know what dark magic Xcode is doing, but here's two helper methods I wrote to easily instantiate any Storyboard VC - you just need the Storyboard name and VC identifier (optionally, otherwise will initial VC). By splitting up my VCs into many different Storyboards, I avoid dealing with xibs while still keeping things simple. One loads it into a nav controller of your choice, the other just returns it by itself:
struct StoryboardHelper {
///instantiates a VC with (optional) identifier viewController from storyboardName, pushes it to hierarcy of navigationController, and runs setup block on it, animated specifies whether the push is animated
internal static func showStoryboard(storyboardName: String, viewController: String?, navigationController: UINavigationController, animated: Bool = true, setup: (UIViewController) -> () ){
let storyboard = UIStoryboard(name: storyboardName, bundle: nil)
let destinationVC = viewController != nil ? storyboard.instantiateViewControllerWithIdentifier(viewController!) : storyboard.instantiateInitialViewController()!
setup(destinationVC)
navigationController.pushViewController(destinationVC, animated: animated)
}
///instantiates and returns a VC with (optional) identifier viewController from storyboardName
internal static func instantiateViewControllerFromStoryboard(storyboardName: String, viewController: String?) -> UIViewController{
let storyboard = UIStoryboard(name: storyboardName, bundle: nil)
return viewController != nil ? storyboard.instantiateViewControllerWithIdentifier(viewController!) : storyboard.instantiateInitialViewController()!
}
}
My segue is returning with an error (unwrapping an optional value) from this line > self.navigationController?....
In my code...
let nextScreen = self.storyboard!.instantiateViewControllerWithIdentifier("onboarding-what") as? ViewController
self.navigationController?.pushViewController(nextScreen!, animated: true)
This above code is implemented in my onboarding-start view controller
This is my storyboard set up...
the last view controller has the id of "onboarding-what".
I've read the documentation for the navigation controller but can't seem to find my problem. Does anyone have a solution?
You can use performSegueWithIdentifier rather than pushViewController if you connected them in storyboard
However did you fill "onboarding-what" in the storyboardId field?
pls check this image
Also "onboarding-what" view controller should be instance of ViewController
(There's not default class called "ViewController" only "UIViewController" or "NSViewController" for osX.)
Obviously nextScreen is nil. It is most likely that "onboarding-what" identifier is incorrect