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.
Related
I have the following code to prepare for my segue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Make sure we are acting on the correct segue
if segue.identifier == "CreateJumpSpot", let jumpSpotCreatorControllerVC = segue.destination as? JumpSpotCreatorController {
// Set the delegate in the JumpSpotCreatorController we're navigating to
jumpSpotCreatorControllerVC.delegate = self
} else if segue.identifier == "JumpSpotInfo", let jumpSpotInfoVC = segue.destination as? JumpSpotInfoController {
if let senderAnnotationView = sender as? JumpSpotAnnotationView {
jumpSpotInfoVC.titleLabel.text = senderAnnotationView.annotation?.title as? String
jumpSpotInfoVC.imageView.image = senderAnnotationView.annotation.
}
}
}
We are focusing on the 'else if' part of the statement here. I have a custom annotation and annotation view. I am populating labels and imageViews in the view controller that I am segueing to, using the properties of the annotation that the user clicked on to reveal the .detailDisclosure version of the rightCalloutAccessoryView. However that sender (.detailDisclosure of rightCalloutAccessoryView) is only allowing me to access the title and subtitle of the annotation. As you can see when I got to the image property I stopped typing, as there was no property to access. How can I access the properties of my custom annotation?
Can‘t you just get the image by senderAnnotationView.annotation?.image, just like what you are doing to get the title?
PS: Don't depend too much on Xcode autocompletion. Sometimes it's doesn't work perfectly well.
Ok I figured it out. All I had to do was adjust the code so that I had a constant of the annotation itself, and cast it as my custom class. Here's the code:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Make sure we are acting on the correct segue
if segue.identifier == "CreateJumpSpot", let jumpSpotCreatorControllerVC = segue.destination as? JumpSpotCreatorController {
// Set the delegate in the JumpSpotCreatorController we're navigating to
jumpSpotCreatorControllerVC.delegate = self
} else if segue.identifier == "JumpSpotInfo", let jumpSpotInfoVC = segue.destination as? JumpSpotInfoController {
if let senderAnnotationView = sender as? JumpSpotAnnotationView {
let senderAnnotation = senderAnnotationView.annotation as? JumpSpotAnnotation
jumpSpotInfoVC.titleLabel.text = senderAnnotation?.title
jumpSpotInfoVC.imageView.image = senderAnnotation?.image
jumpSpotInfoVC.descriptionLabel.text = senderAnnotation?.description
jumpSpotInfoVC.heightLabel.text = senderAnnotation?.estimatedHeight
jumpSpotInfoVC.warningsLabel.text = senderAnnotation?.warnings
}
}
}
The key line there is: let senderAnnotation = senderAnnotationView.annotation as? JumpSpotAnnotation
I have a show-type segue. I want destinationViewController nameTextField to contain some text in it when segue is performed. I tried doing:
override func prepare (for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ToEditScreen" {
let svc = segue.destination as! EditViewController
svc.nameTextField.text = cars[selectedIndex!].name //crashes
svc.nameString = cars[selectedIndex!].name
}
}
The error I get is: Unexpectedly found nil while implicitly unwrapping an Optional value.
I know that cars[selectedIndex!].name is not nil.
If I delete the textfield line everything is fine and nameString does get its value which is equal to cars[selectedIndex!].name. I know I can do:
nameTextField.text = randomString
but it seems like an extra step. Can I populate textfield.text from original ViewController?
You can add a string variable to the destination vc and set it there or
let svc = segue.destination as! EditViewController
svc.loadViewIfNeeded() // add this line
svc.nameTextField.text = cars[selectedIndex!].name
Im unable to update labels in container view. Here's how i've done it.
I wrote my updateWeather function in main VC and retrieved the weather data successfully. when i printed weatherJSON it shows all the received data in console.
now when i started writing updateUI function i could only update the labels on main VC.
so i used prepare segue to send data to container view and sent a string to container VC and updated "humidity" label successfully. all labels accept strings without any issues.
but i have no idea how to send weather data to container view.
i tried passing values using object weatherDataModel but nothing happens. i even declared a new object referring to container view class and used it in updateUI function to set label values but it won't work too.
I have no idea what to pass in place of string to get weather data through to next VC.
override func prepare(for segue: UIStoryboardSegue, sender for: Any?) {
if segue.identifier == "displayFullWeatherInfo"{
let destinationVC = segue.destination as! FullWeatherViewController
destinationVC.delegate = "\(weatherDataModel.pressure)"
....
....
Heres my WeatherDataModel Class:
import Foundation
class WeatherDataModel{
var city = ""
var temp = 0
var country = ""
var humidity = 0
}
in my main VC i have created weatherDataModel object and here's my updateWeatherInfo code:
func updateWeatherInfo(json : JSON){
if let tempDefault = json["data"][0]["temp"].double{
weatherDataModel.temp = Int(tempDefault)
weatherDataModel.city = json["data"][0["city_name"].stringValue
weatherDataModel.country = json["data"][0]["country_code"].stringValue
weatherDataModel.humidity = json["data"][0]["rh"].intValue
updateWeatherUI()
}
else{
currentLocation.text = "Not Available"
}
}
Create a property for your weather model object in your second VC FullWeatherViewController:
var weatherDataModel: WeatherDataModel! //your object
And in your first VC:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "displayFullWeatherInfo" {
let destinationVC = segue.destination as! FullWeatherViewController
destinationVC.weatherDataModel = weatherDataModel
}
I am trying to take facebook values, such as name and email, and transferring them to another view controller where they populate their corresponding text fields. However, when I try to populate the text fields with this code
let fbEmail = data["email"]
let fbName = data["name"]
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as? CreateAccountVC
vc!.emailTxt = self.fbName
vc!.fullnameTxt = self.fbEmail
}
I receive an error saying "Cannot assign type String to type UITextField!" I'm confused here as I thought that text fields only take strings (I'm very new to coding/programming).
So basically, how do I get these values gathered in one view controller to populate text fields in another view controller? Any help would be greatly appreciated! Thanks!
Error reason is you need to assign it to the UITextField's text property.
You can also use variables to set them. And set textfield's values in your CreateAccountVC controller's viewDidLoad function. Like this:
Your first controller where you take facebook values:
let fbEmail = data["email"]
let fbName = data["name"]
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? CreateAccountVC {
vc.emailTxtValue = self.fbName
vc.fullnameTxtValue = self.fbEmail
}
}
Your CreateAccountVC :
class CreateAccountVC: UIViewController {
var emailTxtValue:String?
var fullnameTxtValue:String?
override func viewDidLoad() {
super.viewDidLoad()
emailTxt.text = emailTxtValue
fullnameTxt.text = fullnameTxtValue
}
}
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
}
}