Swift 3将数据从一个ViewController传递到另一个ViewController

时间:2021-01-13 16:02:44

I am new to IOS programming and don't really know what I'm asking but I will try and explain

我是IOS编程的新手,并不知道我在问什么,但我会尝试解释

I am using Firebase to auth and then I want to take the UID and pass it to a different VC the problem I am getting I cant get the var userID to print out side of the IBAction here is where I am so far, any pointer would get good cheers guys

我正在使用Firebase进行身份验证,然后我想取UID并将其传递给另一个VC我遇到的问题我无法获取var userID以打印出IBAction的一面这里是我到目前为止,任何指针都会得到好欢呼的家伙

@IBAction func creatAccountPressed(_ sender: Any) {
    if let email = emailTextField.text,
        let password = passwordTextField.text,
        let name = nameTextField.text {
        Auth.auth().createUser(withEmail: email, password: password, completion: { user, error in
            if let firebaseError = error {
                print(firebaseError.localizedDescription)
            }
            let userID            = user!.uid
            let userEmail: String = self.emailTextField.text!
            let fullName: String  = self.nameTextField.text!
            self.ref.child("users").child(userID).setValue(["Email": userEmail, "Name": fullName])
            self.userID1          = user!.uid as! String
        })
        print(self.userID1)
        presentLoggedInScreen()
    }
}

func presentLoggedInScreen() {
    let stroyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    let loggedInVC: LoggedInVCViewController = stroyboard.instantiateViewController(withIdentifier: "loggedInVC") as! LoggedInVCViewController
    self.present(loggedInVC, animated: true, completion: nil)
}

2 个解决方案

#1


1  

One the simpler way to pass info from one VC to another is either through an initiliazer, or through a variable that you set before presenting the second VC.

将信息从一个VC传递到另一个VC的简单方法是通过initiliazer,或者通过在呈现第二个VC之前设置的变量。

Since you are new to this, try the variable approach for now, so if say, you're passing a string:

由于你是新手,现在尝试变量方法,所以如果说,你要传递一个字符串:

class LoggedInVCViewController : UIViewController {

    var info : String? {
       didSet {
          if let newInfo = self.info {
             //do what ever you need to do here
          }
       }
    }

    override viewDidLoad() {
       super.viewDidLoad()

    }

}

func presentLoggedInScreen(yourInfo: String) { 
   let stroyboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil) 
   let loggedInVC:LoggedInVCViewController = 
   storyboard.instantiateViewController(withIdentifier: "loggedInVC") as! 
   LoggedInVCViewController 
   loggedInVC.info = yourInfo
   self.present(loggedInVC, animated: true, completion: nil) 
}

Mind you, you can always use any other king of variable Class for info. You also would program your VC to execute some methods inside of the get bracket of the property, populate some fields based on the content of info, load a specific UI etc.

请注意,您可以随时使用任何其他可变类王来获取信息。您还可以编程VC以在属性的get括号内执行某些方法,根据info的内容填充一些字段,加载特定的UI等。

Another usefull way is to go the initialization route, but unfortunately you cannot use it with Storyboard nibs (sad i know, but this post goes over this nicely), but it still usefull whenever you will feel comfortable enough to initialize and design VC's programmatically (which I would learn ASAP if were you).

另一个有用的方法是进入初始化路线,但不幸的是你不能将它与Storyboard笔尖一起使用(我知道很难过,但这篇文章很好地解释了这一点),但是只要你感觉足够舒适地以编程方式初始化和设计VC,它仍然有用(如果你是我,我会尽快学习)。

You pass a variable in a custom intializer method for your VC:

您在VC的自定义intializer方法中传递变量:

class LoggedInVCViewController : UIViewController {

    var info : Any? {
        get {
            if let this = self.info {
                return this
            } else {
                return nil
            }
        } set {
            if let new = newValue {
                //
            }
        }
    }

    init(info: Any?) {
        //This first line is key, it also calls viewDidLoad() internally, so don't re-write viewDidLoad() here!!
        super.init(nibName: nil, bundle: nil)

        if let newInfo = info {
            //here we check info for whatever you pass to it
            self.info = newInfo
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

So you would use is as:

所以你会使用如下:

func presentLoggedInScreen(yourInfo: String) {
        let loggedInVC = LoggedInVCViewController(info: yourInfo)
        self.present(loggedInVC, animated: true, completion: nil)
}

Obviously, as stated, this method cannot be used with Storyboards, but very usefull and, as I'm sure you can see, is much more compact.

显然,如上所述,这种方法不能与Storyboard一起使用,但非常有用,而且我相信你可以看到,它更加紧凑。

I suggest you get familiar with Swift Properties of the docs, along with some blog tips such as this one. You can get pretty creative after a while.

我建议你熟悉文档的Swift Properties,以及一些博客提示,比如这个。一段时间后你可以变得非常有创意。

For learning more programmatic approaches, i strongly recommend this YouTube channel: Let's Build That App, I personnaly haven't found a better reference point for programmatic approach Swift programming.

为了学习更多的程序化方法,我强烈推荐这个YouTube频道:让我们构建那个应用程序,我个人还没有找到一个更好的参考点来进行程序化方法Swift编程。

Don't hesitate to ask questions!

不要犹豫提问!

UPDATE

UPDATE

Your IBAction should look like this:

您的IBAction应如下所示:

@IBAction func creatAccountPressed(_ sender: Any) {
    if let email = emailTextField.text, let password = passwordTextField.text, let name = nameTextField.text {
        Auth.auth().createUser(withEmail: email, password: password, completion: { user, error in
            if let firebaseError = error {
                print(firebaseError.localizedDescription)
                }


            let userID = user!.uid
            let userEmail: String = self.emailTextField.text!
            let fullName: String = self.nameTextField.text!

            self.ref.child("users").child(userID).setValue(["Email": userEmail, "Name": fullName])

           self.userID1 = user!.uid as! String

           print(self.userID1)

           presentLoggedInScreen(yourInfo: self.userID1)


        })

    }
}

#2


0  

Put

print(self.userID1)

presentLoggedInScreen()

inside the completion block. Currently those lines are almost certain to happen before the completion block is done as the block is executed after the required network calls return.

在完成块内。目前,这些行几乎肯定会在完成块完成之前发生,因为在所需的网络调用返回之后执行块。

Be sure to wrap presentLoggedInScreen() in a block that dispatches it to the main thread as it touches the UI and all UI calls must be made from the main thread.

确保将presentLoggedInScreen()包装在一个块中,该块在接触UI时将其分派给主线程,并且必须从主线程进行所有UI调用。

DispatchQueue.main.async {
  presentLoggedInScreen()
}

This will make it so that presentLoggedInScreen() executes after the value as been assigned to userID1 allowing you to pass the value over to the incoming view controller (assuming, of course, that the incoming VC has an appropriate variable to pass userID1 into).

这将使presentLoggedInScreen()在分配给userID1的值之后执行,允许您将值传递给传入的视图控制器(当然,假设传入的VC具有适当的变量以将userID1传递到其中)。

Something like:

就像是:

loggedInVC.userID = self.userID1

before you present the VC.

在你呈现VC之前。

#1


1  

One the simpler way to pass info from one VC to another is either through an initiliazer, or through a variable that you set before presenting the second VC.

将信息从一个VC传递到另一个VC的简单方法是通过initiliazer,或者通过在呈现第二个VC之前设置的变量。

Since you are new to this, try the variable approach for now, so if say, you're passing a string:

由于你是新手,现在尝试变量方法,所以如果说,你要传递一个字符串:

class LoggedInVCViewController : UIViewController {

    var info : String? {
       didSet {
          if let newInfo = self.info {
             //do what ever you need to do here
          }
       }
    }

    override viewDidLoad() {
       super.viewDidLoad()

    }

}

func presentLoggedInScreen(yourInfo: String) { 
   let stroyboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil) 
   let loggedInVC:LoggedInVCViewController = 
   storyboard.instantiateViewController(withIdentifier: "loggedInVC") as! 
   LoggedInVCViewController 
   loggedInVC.info = yourInfo
   self.present(loggedInVC, animated: true, completion: nil) 
}

Mind you, you can always use any other king of variable Class for info. You also would program your VC to execute some methods inside of the get bracket of the property, populate some fields based on the content of info, load a specific UI etc.

请注意,您可以随时使用任何其他可变类王来获取信息。您还可以编程VC以在属性的get括号内执行某些方法,根据info的内容填充一些字段,加载特定的UI等。

Another usefull way is to go the initialization route, but unfortunately you cannot use it with Storyboard nibs (sad i know, but this post goes over this nicely), but it still usefull whenever you will feel comfortable enough to initialize and design VC's programmatically (which I would learn ASAP if were you).

另一个有用的方法是进入初始化路线,但不幸的是你不能将它与Storyboard笔尖一起使用(我知道很难过,但这篇文章很好地解释了这一点),但是只要你感觉足够舒适地以编程方式初始化和设计VC,它仍然有用(如果你是我,我会尽快学习)。

You pass a variable in a custom intializer method for your VC:

您在VC的自定义intializer方法中传递变量:

class LoggedInVCViewController : UIViewController {

    var info : Any? {
        get {
            if let this = self.info {
                return this
            } else {
                return nil
            }
        } set {
            if let new = newValue {
                //
            }
        }
    }

    init(info: Any?) {
        //This first line is key, it also calls viewDidLoad() internally, so don't re-write viewDidLoad() here!!
        super.init(nibName: nil, bundle: nil)

        if let newInfo = info {
            //here we check info for whatever you pass to it
            self.info = newInfo
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

So you would use is as:

所以你会使用如下:

func presentLoggedInScreen(yourInfo: String) {
        let loggedInVC = LoggedInVCViewController(info: yourInfo)
        self.present(loggedInVC, animated: true, completion: nil)
}

Obviously, as stated, this method cannot be used with Storyboards, but very usefull and, as I'm sure you can see, is much more compact.

显然,如上所述,这种方法不能与Storyboard一起使用,但非常有用,而且我相信你可以看到,它更加紧凑。

I suggest you get familiar with Swift Properties of the docs, along with some blog tips such as this one. You can get pretty creative after a while.

我建议你熟悉文档的Swift Properties,以及一些博客提示,比如这个。一段时间后你可以变得非常有创意。

For learning more programmatic approaches, i strongly recommend this YouTube channel: Let's Build That App, I personnaly haven't found a better reference point for programmatic approach Swift programming.

为了学习更多的程序化方法,我强烈推荐这个YouTube频道:让我们构建那个应用程序,我个人还没有找到一个更好的参考点来进行程序化方法Swift编程。

Don't hesitate to ask questions!

不要犹豫提问!

UPDATE

UPDATE

Your IBAction should look like this:

您的IBAction应如下所示:

@IBAction func creatAccountPressed(_ sender: Any) {
    if let email = emailTextField.text, let password = passwordTextField.text, let name = nameTextField.text {
        Auth.auth().createUser(withEmail: email, password: password, completion: { user, error in
            if let firebaseError = error {
                print(firebaseError.localizedDescription)
                }


            let userID = user!.uid
            let userEmail: String = self.emailTextField.text!
            let fullName: String = self.nameTextField.text!

            self.ref.child("users").child(userID).setValue(["Email": userEmail, "Name": fullName])

           self.userID1 = user!.uid as! String

           print(self.userID1)

           presentLoggedInScreen(yourInfo: self.userID1)


        })

    }
}

#2


0  

Put

print(self.userID1)

presentLoggedInScreen()

inside the completion block. Currently those lines are almost certain to happen before the completion block is done as the block is executed after the required network calls return.

在完成块内。目前,这些行几乎肯定会在完成块完成之前发生,因为在所需的网络调用返回之后执行块。

Be sure to wrap presentLoggedInScreen() in a block that dispatches it to the main thread as it touches the UI and all UI calls must be made from the main thread.

确保将presentLoggedInScreen()包装在一个块中,该块在接触UI时将其分派给主线程,并且必须从主线程进行所有UI调用。

DispatchQueue.main.async {
  presentLoggedInScreen()
}

This will make it so that presentLoggedInScreen() executes after the value as been assigned to userID1 allowing you to pass the value over to the incoming view controller (assuming, of course, that the incoming VC has an appropriate variable to pass userID1 into).

这将使presentLoggedInScreen()在分配给userID1的值之后执行,允许您将值传递给传入的视图控制器(当然,假设传入的VC具有适当的变量以将userID1传递到其中)。

Something like:

就像是:

loggedInVC.userID = self.userID1

before you present the VC.

在你呈现VC之前。