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
}
}
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
This is a learning app that I am making for fun, I have been stuck here for 2 days.
I have two views setup that I use to send data that the user will pick to the other one (they are named AddCoinVC and MainVC).
In AddCoinVC, the sending is performed when the user clicks on the button
let vc = MainViewController()
vc.coinArray.append(CoinWallet(coinName: "Test", coinSymbol: "Test", coinAmount: "0"))
performSegue(withIdentifier: "backToMain", sender: self)
I have setup a breakpoint at this point and printing vc.coinArray prints me the correct value =
($R0 = 1 value { (coinName = "Test", coinSymbol = "Test", coinAmount = "0")
}
But when I go to my other breakpoint at MainVC, it displays 0 value.
var coinArray = [CoinWallet]()
This is the var that I use, the default in MainVC is CoinWallet which is empty when first loading the app. This is the custom Class.
class CoinWallet {
var coinName:String = ""
var coinSymbol:String = ""
var coinAmount:String = ""
init(coinName: String, coinSymbol:String, coinAmount: String) {
self.coinName = coinName
self.coinSymbol = coinSymbol
self.coinAmount = coinAmount
}
}
When the segue and the sending is performed from AddCoinVC to MainVC 'coinArray' should have this value sent to it.
Why would be the value empty if vc.coinArray has 1 value?
The error occurs because MainViewController() does not return the view controller you expect. It's a new blank instance which is not the instance in the storyboard.
Since you are performing a segue anyway, pass the CoinWallet instance as sender parameter in performSegue
let coin = CoinWallet(coinName: "Test", coinSymbol: "Test", coinAmount: "0")
performSegue(withIdentifier: "backToMain", sender: coin)
Then implement prepare(for segue and use the destination property as reference to the main view controller.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "backToMain" {
let coin = sender as! CoinWallet
let mainViewController = segue.destination as! MainViewController
mainViewController.coinArray.append(coin)
}
}
You should add this method in your AddCoinVC and send data as below,
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let mainVC = segue.destination as? MainViewController {
mainVC.coinArray.append(CoinWallet(coinName: "Test", coinSymbol: "Test", coinAmount: "0"))
}
}
In the below lines of code, you are just creating a new instance that is not the viewController being segued.
let vc = MainViewController()
vc.coinArray.append(CoinWallet(coinName: "Test", coinSymbol: "Test", coinAmount: "0"))
You should only perform the segue on button click as below and set any data inside the above method.
performSegue(withIdentifier: "backToMain", sender: self)
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 have a MapViewController with a prepareForSegue(_:sender:)method, which I intend to use to send data to LandmarkTableViewController, and is called when a button is pressed.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let destinationvc = segue.destinationViewController
if let landmarkvc = destinationvc as? LandmarkTableViewController {
if let identifier = segue.identifier {
let library = Landmark(name: "Run Run Shaw Library", properties: ["Chinese Kanji", "Gray", "Green Plants"])
let bank = Landmark(name: "Hang Seng Bank", properties: ["Chinese Kanji", "Green"])
switch identifier {
case "showLibrary" : landmarkvc.passedLandmark = library // pass data to LandmarkTableViewController
case "showBank" : landmarkvc.passedLandmark = bank // pass data to LandmarkTableViewController
default : break
}
}
}
}
The LandmarkTableViewController is properly set up to display the String array properties, with one String on each row. So what I intend to do is pass the appropriate data for the table to properties according to which button was pressed, and let LandmarkTableViewController display the corresponding properties.
class LandmarkTableViewController: UITableViewController {
var properties = [String]()
var passedLandmark = Landmark(name: "temp", properties: ["temp"]) // initially set to default value
override func viewDidLoad() {
super.viewDidLoad()
loadSampleProperties()
}
func loadSampleProperties() {
self.properties = passedLandmark!.properties
}
// other methods....
}
class Landmark {
var name: String
var properties: [String]
init?(name: String, properties: [String]) {
self.name = name
self.properties = properties
// Initialization should fail if there is no name or if there is no property.
if name.isEmpty || properties.isEmpty {
return nil
}
}
However, when I run the code, only temp is displayed in the table view. I've been stuck on this for a long time now, so any help is much appreciated!
Edit: loadData() inside of viewDidLoad() is changed to the correct loadSampleProperties(). I made an error while posting the code to the question.
I think this should solve your problem if not double check your identifiers
and you can make sure to data passing with adding print(passedLandmark) to viewDidLoad() or breakpoint to make sure you getting the data
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let destinationvc = segue.destinationViewController
if let landmarkvc = destinationvc as? LandmarkTableViewController {
if segue.identifier == "showLibrary" {
let library = Landmark(name: "Run Run Shaw Library", properties: ["Chinese Kanji", "Gray", "Green Plants"])
landmarkvc.passedLandmark = library
}
if segue.identifier == "showBank" {
let bank = Landmark(name: "Hang Seng Bank", properties: ["Chinese Kanji", "Green"])
landmarkvc.passedLandmark = bank
}
}
}
Hope this will helps
Code is missing from your quote, so I can't be sure, but I assume your loadData() method is the one that reloads the table view data with Landmark you've passed in prepareForSegue. If that is the case:
viewDidLoad() is called before prepareForSegue, so that all the views and elements of the destinationViewController are loaded and ready to use. Thus, in your case, the table view is loaded with your "temp" data and nothing makes it reload when you set the proper one.
You have two options:
You could call loadData()/reloadData() in viewWillAppear for example, which is called after prepareForSegue(). Bare in mind that viewWillAppear will possibly be called again in some other navigation.
Otherwise, you could instantiate and present/push the new controller in your parent view controller, instead of using the segue.
i want to make when user login in the login view controller, the email saved and display to slide out menu view controller, but the slide out menu displayed first when build and run. So the variable contains nothing because user haven't login yet in login view controller.
im using this to declare the text in text field is email fill
let emailFill:String = self.emailTextfield.text!
and use
self.labelContainEmail = emailFill
the labelContainEmail is a global variable at top
var labelContainEmail: String = ""
i'm using prepare for segue like this to move data
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier == "yolo"
{
let vc = segue.destinationViewController as! SlideOutMenu
vc.labelContainEmail2 = labelContainEmail
print(vc.labelContainEmail2) // this don't print anything, but when i print under `self.labelContainEmail = emailFill` it printed out the email
}
}
in the slideOutMenu.swift, i have this var at top
var labelContainEmail2: String = ""
and try to change the label text with
labelEmail.text = labelContainEmail2
in the view did Load
what should i do? please go easy, i'm new to swift
using prepare for segue store email in NSUserDefaults
NSUserDefaults.standardUserDefaults().setObject(labelContainEmail , forKey: "email") // save user email
in the slideOutMenu.swift and try to change the label text with in the view did Load
if (NSUserDefaults.standardUserDefaults().objectForKey("email")) == nil
{
NSUserDefaults.standardUserDefaults().setObject("" , forKey: "email")
}
else
{
let emailStr = NSUserDefaults.standardUserDefaults().objectForKey("email") as! String
}
You can use on the top this line
** Second View
class SlideOutMenu: UIViewController {
var labelContainEmail: String?
//your code here
}
Where you are going from first view to second view.
**Use First View
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier == "yolo"
{
let vc = segue.destinationViewController as! SlideOutMenu
vc.labelContainEmail2 = labelContainEmail
print(vc.labelContainEmail2) // this don't print anything, but when i print under `self.labelContainEmail = emailFill` it printed out the email
}
}
i hope it will help you other wise you can use Model Class also better way for pass data.