0

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

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

@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)
}
aashish tamsya
  • 4,903
  • 3
  • 23
  • 34
Paul Smith
  • 5
  • 1
  • 8
  • 1
    show your function presentLoggedInScreen() – J. Doe Jul 05 '17 at 20:15
  • 1
    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) } – Paul Smith Jul 05 '17 at 20:16
  • @PaulSmith Do not post code in comments. Please [edit] your question with all relevant details. – rmaddy Jul 05 '17 at 20:26

2 Answers2

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.

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.

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

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

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.

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.

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.

Don't hesitate to ask questions!

UPDATE

Your IBAction should look like this:

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


        })

    }
}
jlmurph
  • 1,050
  • 8
  • 17
  • Thank you for the reply, i will have a look at the youtube vid. your method at the top works but the problem i have is the userID1 gets its value inside the IBAction so when i try and print it or do anything with it it doesn't work, am i right is saying if you have a var inside a IBAction there is no way to use it outside that action ? – Paul Smith Jul 05 '17 at 21:11
  • There is a way, like the other replyer, you just need to put the print() and the present method inside the completion block, but also, like my answer is showing you, you need to access that variable from inside of presentLoggedInScreen. Either of my approach (passing the userID as a parameter), or accessing it from inside the method, should work. – jlmurph Jul 05 '17 at 21:15
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.

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

Something like:

loggedInVC.userID = self.userID1

before you present the VC.

theMikeSwan
  • 4,739
  • 2
  • 31
  • 44