Reputation: 39
I'm trying to use a Struct to pass some variables that I get from a Facebook Graph Request such as email, name, gender, etc. I've created the Struct ('fbDemographics') and the variables in 'ViewController' but I get an error when I try to call the struct and one of the variables in 'SecondViewController' (Type 'ViewController' has no member 'fbDemographics'). I've never used struct before so a bit baffled why I am getting this error. Thanks for any thoughts. The code for both view controllers is below:
class ViewController: UIViewController, FBSDKLoginButtonDelegate {
override func viewDidLoad() {
super.viewDidLoad()
struct fbDemographics {
static var relationship_status: String?
static var gender: String?
static var user_education_history: String?
static var user_location: String?
static var email: String?
static var name: String?
}
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, relationship_status, gender, user_location, user_education_history, email"]).start(completionHandler: { (connection, result, error) -> Void in
if (error == nil){
//let fbDetails = result as! NSDictionary
//print(fbDetails)
if let userDataDict = result as? NSDictionary {
fbDemographics.gender = userDataDict["gender"] as? String
fbDemographics.email = userDataDict["email"] as? String
fbDemographics.name = userDataDict["name"] as? String
fbDemographics.user_location = userDataDict["user_location"] as? String
fbDemographics.user_education_history = userDataDict["user_education_history"] as? String
fbDemographics.relationship_status = userDataDict["relationship_status"] as? String
let myEducation = fbDemographics.user_education_history
let myEmail = fbDemographics.email
let myGender = fbDemographics.gender
let myName = fbDemographics.name
let myStatus = fbDemographics.relationship_status
let myLocation = fbDemographics.user_location
self.performSegue(withIdentifier: "LoginToHome", sender: (Any).self)
}
}
SECOND VIEW CONTROLLER
class SecondViewController: UIViewController {
@IBAction func verticalSliderChanged(_ sender: UISlider) {
let currentValue = String(sender.value);
sliderLabel.text = "\(currentValue)"
func viewDidLoad() {
super.viewDidLoad()
***ViewController.fbDemographics.myEmail***
}
}
Upvotes: 1
Views: 3967
Reputation: 437382
The problem is that you've defined your struct
inside viewDidLoad
. So the scope is limited to that method. Move it out of viewDidLoad
, but still in ViewController
, and you should be able to access it from the SecondViewController
. Obviously, you'll have to fix that reference to myEmail
, too, because it's called email
. Also, in your SecondViewController
you should pull viewDidLoad
implementation out of the verticalSliderChanged
method; the viewDidLoad
should be a top-level instance method of SecondViewController
, not defined inside another method.
There are deeper problems here, though. Rather than using struct
with static
variables, you really should make those simple instance variables, create an instance of your FbDemographics
type (note, start struct
types with uppercase letter), and then pass this instance in prepare(for:sender:)
.
For example, the right way to pass data would be to:
static
variables;struct
a name that starts with uppercase letter;struct
; andprepare(for:sender:)
.E.g.
struct FbDemographics {
var relationshipStatus: String?
var gender: String?
var userEducationHistory: String?
var userLocation: String?
var email: String?
var name: String?
}
class ViewController: UIViewController {
var demographics: FbDemographics?
override func viewDidLoad() {
super.viewDidLoad()
performRequest() // I actually don't think you should be initiating this in `viewDidLoad` ... perhaps in `viewDidAppear`
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? SecondViewController {
destination.demographics = demographics
}
}
func performRequest() {
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, relationship_status, gender, user_location, user_education_history, email"]).start { connection, result, error in
guard let userDataDict = result as? NSDictionary, error == nil else {
print("\(error)")
return
}
self.demographics = FbDemographics(
relationshipStatus: userDataDict["relationship_status"] as? String,
gender: userDataDict["gender"] as? String,
userEducationHistory: userDataDict["user_education_history"] as? String,
userLocation: userDataDict["user_location"] as? String,
email: userDataDict["email"] as? String,
name: userDataDict["name"] as? String
)
self.performSegue(withIdentifier: "LoginToHome", sender: self)
}
}
}
And then SecondViewController could:
class SecondViewController: UIViewController {
var demographics: FbDemographics!
override func viewDidLoad() {
super.viewDidLoad()
let value = demographics.email // this should work fine here
}
}
Upvotes: 3