Pass data via 'prepareForSegue' in Swift 2 - ios

Trying to pass a string from one view controller to another view controller (MoreDetailViewController)
Coming up with this error :
unknown class MoreDetailViewController in Interface Builder file.
Could not cast value of type 'UIViewController' (0x10f4ae308) to 'ParseStarterProject_Swift.MoreDetailViewController' (0x10d512060).
(lldb)
Sorry if this is obvious, but I have only recently started coding. Thank you! :)
Code :
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "showDetail") {
let detailController : MoreDetailViewController = segue.destinationViewController as! MoreDetailViewController
detailController.receivedId = selectedId
}
}

Is your second view controller correctly set as a MoreDetailViewController in Interface Builder ?
You can check it easily : Open your .xib or .storyboard file, select your second view controller, and on the Identity Inspector (right panel, third tab) enter your class name.

The error is simply saying that the segue destination viewcontroller is not a MoreDetailViewController. You should also not force unwrap it, in which case it will crash if the object is not correct.
if segue.identifier == "showDetail" {
if let vc = segue.destinationViewController as? MoreDetailViewController {
vc.receivedId = selectedId
}
}
Edit
Did not see previous answer which was the exact same code. Sorry about that.

Try this :
if segue.identifier == "showDetail"
{
if let detailController = segue.destinationViewController as? MoreDetailViewController
{
detailController.receivedId = selectedId
}
}
Note: Don't forget to set viewcontroller class as MoreDetailViewController

Related

Value of type 'HistoryViewController' has no member 'match'

I cannot figure out what the error "Value of type 'HistoryViewController' has no member 'match'" is telling me. Directly above, similar code seems to work:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "throwDownScissors" {
let controller = segue.destination as! ResultViewController
controller.match = self.match
}
else if segue.identifier == "showHistory" {
let controller = segue.destination as! HistoryViewController
controller.match = self.match
}
}
Why does the second bit of code trigger the error?
It seems that your ResultViewController has a match property declared inside it but HistoryViewController doesn't have this property so when the if statment go through the else condition it cannot call the match property which is not existing since you force casted the destination controller to HistoryViewController

Prepare for segue function not loading new values

The statValue attribute of my UIButton class has been updated since the segue was last called, but the segue still sends the old, original value. Is there a way to refresh the prepare function (below) so that it sends the new value?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "StatDetailSegue" {
if let destinationVC = segue.destination as? StatDetailViewController,
let index = (sender as? StatButton)?.buttonIndex,
let sendVal = (sender as? StatButton)?.buttonValue,
let sendUnit = (sender as? StatButton)?.buttonUnit,
let sendTitle = (sender as? StatButton)?.detailTitle {
destinationVC.statID = index
destinationVC.statValue = sendVal
destinationVC.statUnit = sendUnit
destinationVC.statTitle = sendTitle
print("Destination STATID: \(destinationVC.statID)")
print("Destination value: \(destinationVC.statValue)")
}
}
}
Check your StatButton if you using in storyboard your buttons , then your button should inherit from StatButton instead of UIButton otherwise your code looks fine.
Can you debug the value of statValue in your destinationVC and check if it gets updated after the destinationVC is presented? Also, check the implementation of 'StatButton' class, maybe the buttonValue property is a lazily initialized property and initialized only once? That's why maybe you keep getting the first value that was assigned to the buttonValue always.

Could not cast value of type 'UINavigationController' to 'jacrs_ios.TopViewController'

I'm new to Swift and I was trying to make a side menu base on the tutorial that I was following but I ran across with this error. "Could not cast value of type 'UINavigationController' (0x1026054a8) to 'jacrs_ios.TopViewController' (0x1009ac510)." I noticed that there were same problems already existing here but I still dont understand. I'm gonna included the current storyboard in case I did something wrong. Thanks.
ViewController Error
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let topViewController = segue.destination as! TopViewController
topViewController.stringPassed = userName.text!
}
Storyboard
Try this
if let navigationController = segue.destination as? UINavigationController
{
let topViewController = navigationController?.topViewController as! TopViewController
topViewController.stringPassed = userName.text!
}

Value of type 'UIViewController' has no member 'jsonfile' named JSON

I currently have a button set to go to a TableViewController but decided I wanted to embed that TableViewController in a TabBarController. I am running into an error while trying to pass it to the UITabBarController.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "showListSegue") {
let tabBarController = segue.destinationViewController as! UITabBarController
tabBarController.selectedIndex = 0 // choose which tab is selected
let des = tabBarController.selectedViewController!
des.jsonfile = self.jsonfile
}
}
In the last line of code, des.jsonfile = self.jsonfile, I am getting the error...
Value of type 'UIViewController' has no member 'jsonfile'
I am trying to pass the jsonfile to the TableViewController which is now embedded in the UITabBarController. How can this be done? I have this variable in the TableViewController is was getting passed to but now that I threw this TabBarController in the mix I am getting all confused.
I also tried to create a Cocoa file for the TabBarcontroller and set the variable var jsonfile : JSON! but that did not work either. (That is the variable in my TableViewController that I want to pass it to) Please help. Thank you.
You need to let the compiler know that selectedViewController is a type with the member jsonFile. Also, you should check that it actually is existing and of the correct class at runtime. Here's the kind of pattern you should be using:
class JSONDisplayController: UIViewController {
var jsonfile: String
}
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "showListSegue") {
guard let tabBarController = segue.destinationViewController as? UITabBarController else {
preconditionFailure("Unexpected destination.")
}
tabBarController.selectedIndex = 0 // choose which tab is selected
guard let des = tabBarController.selectedViewController as? JSONDisplayController else {
preconditionFailure("Unexpected selection.")
}
des.jsonfile = jsonfile
}
}

Pass a string to a second view controller

I'm trying to pass a string to a second view controller. The string is the title of the new view controller.
To pass the string I can use 2 solutions and both solutions work correctly but for me is not so clear the difference. Can someone explain me the differences?
Here the first solution:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "settime") {
let svc = segue.destinationViewController as! timeSetting;
//Assign the new title
svc.toPass = "New Title"
}
}
Here the second solution:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "settime") {
let svc = segue.destinationViewController as? timeSetting;
//Assign the new title
svc!.toPass = "New Title"
}
}
The variable toPass is defined in this way in the second viewController:
var toPass:String = "Title"
Both of your code is working and it works in the same way.
The only difference is about the optional casting.
Optional in Swift
Both solutions will perform the same action. In my opinion, the first solution is preferred because it express your intent more precisely.
By stating let svc = segue.destinationViewController as! timesetting you state that the destination view controller is certain to be of the type timesetting.
The second form tests to see if the destination view controller is of the type timeSetting. If it is, then the variable svc will have a non-nil value.
If you were to define another segue of the same name that presents a different type of view controller, then both solutions will fail; the first one on the as! clause and the second one when you try to unwrap svc!, which would be nil.
They are the same.
If there is a difference, it is the time of unwrap the optional value. In the first solution, the type of svc is timeSetting. In the second solution, the type of svc is timeSetting?.
Both will work but in my opinion the best way is to unwrap the optional like the following:
if let svc = segue.destinationViewController as? timeSerting { svc.toPass = "xx" }

Resources