2017-05-06 85 views
0

我试图使用一个结构来传递我从Facebook图形请求获得的一些变量,如电子邮件,姓名,性别等 我创建了Struct('fbDemographics ')和'ViewController'中的变量,但当我尝试调用结构和'SecondViewController'中的一个变量(类型'ViewController'没有成员'fbDemographics')时出现错误。我从来没有使用过结构,所以有点困惑,为什么我得到这个错误。感谢您的任何想法。两个视图控制器的代码如下:使用结构来传递变量Swift

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) 


      } 


     } 

第二视图控制器

class SecondViewController: UIViewController { 

@IBAction func verticalSliderChanged(_ sender: UISlider) { 

     let currentValue = String(sender.value); 

     sliderLabel.text = "\(currentValue)" 

    func viewDidLoad() { 
     super.viewDidLoad() 

     ***ViewController.fbDemographics.myEmail*** 

    } 
} 
+0

有很多的东西错了你目前的解决方案。我会搜索一些关于在视图控制器之间传递数据的教程。 – nathan

+0

我已经经历了很多教程。只是没有获得传递变量,但我想生病继续堵塞。谢谢参观。 –

+1

你的问题有很多不必要的代码。请删除并保留唯一重要的内容。 – Macabeus

回答

1

的问题是,已经定义了你structviewDidLoad。所以范围仅限于该方法。将其移出viewDidLoad,但仍在ViewController之内,您应该可以从SecondViewController访问它。很明显,您必须修复对myEmail的引用,因为它被称为email。另外,在您的SecondViewController中,您应该将viewDidLoad实施从verticalSliderChanged方法中取出; viewDidLoad应该是SecondViewController的顶级实例方法,而不是在另一个方法内部定义。

虽然这里有更深层次的问题。而不是使用structstatic变量,你真的应该制作这些简单的实例变量,创建一个FbDemographics类型的实例(注意,用大写字母开头struct类型),然后在prepare(for:sender:)中传递这个实例。


例如,要传递数据以正确的方式将是:

  • 消除static变量;
  • 给你的struct一个以大写字母开头的名字;
  • 创建您的struct实例;和
  • 将此实例传递给目标视图控制器prepare(for:sender:)

例如,

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) 
     } 
    } 

} 

然后SecondViewController可以:

class SecondViewController: UIViewController { 

    var demographics: FbDemographics! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     let value = demographics.email // this should work fine here 
    } 

} 
+0

非常感谢您花时间提出这样一个完整的答案。我经历了这一点,并遵循你所说的话。我没有任何错误,这是一个很好的首发。一个问题,但;当你说通过实例(prepareforsegue)时,我不确定你的意思。再次感谢。 –

+0

由于种种原因,声明'static'属性是不可取的(每个'FbDemographics'实例都会共享相同的值)。你反而想用'let foo = FbDemographics(...)'语法创建一个“实例”。然后,问题变成了如何'SecondViewController'得到这个实例的副本。所以你有'prepare(for:sender:)'确认目标是一个'SecondViewController',如果是的话,分配相应的'demographics'属性作为我们上面创建的原始'FbDemographics'实例的副本。 – Rob