1

So in my app, I have a view controller that allows the user to input an email and password into UITextFields, and then I log the user in with Firebase and identify their uid associated with the email. I also have a struct called User which contains username and userID Strings and an array of Strings (I'm not providing the code for it because I don't think it is necessary, but if you need it, let me know).

I have a class level variable

var currentUser:User? = nil

and in the login button's @IBaction method I do the following to initialize a user with a FIRDataSnapshot using the aforementioned uid:

    FIRAuth.auth()?.signIn(withEmail: usernameTextBox.text!, password: passwordTextBox.text!) { (user, error) in
        if error == nil {
            //Valid Email and Password
            let userID = FIRAuth.auth()?.currentUser?.uid

            self.childRef.observe(.value, with: { snapshot in
                for item in snapshot.children.allObjects as! [FIRDataSnapshot] {
                    let dict = item.value as! Dictionary<String,Any>
                    if (dict["UserID"] as? String == userID) {
                        self.currentUser = User(snapshot: item) //<----This is where currentUser is assigned the new User
                    }
                    //currentUser = User(snapshot: )
                    self.performSegue(withIdentifier: "LoginSegue", sender: sender)
                }
            })

        }
        else {
            //Error stuff
        }
    }

My problem is that in another classes I need to access the currentUser variable (to add friends, etc.) but I am not sure how to go about it. I also cannot pull the user data from Firebase in other classes because only the one described above has access to the UserID that I need to identify which user information to use and modify.

I cannot use prepareForSegue because there is an SWRevealViewController in between the one where you login and the other view controllers, and SWRevealViewController is written in Objective-C, which I am not familiar with. My research has revealed that some possibilities may be global variables and singletons, but using either is seen as unsafe practice by many programmers. Also using NSUserDefaults (I think they've been renamed to UserDefaults in Swift 3) is another potential solution? I am open to any suggestions.

Thanks in advance.

RPatel99
  • 7,448
  • 2
  • 37
  • 45
  • Unless someone else mentions another method, it would be best to use NSUserdefaults, unless you can access the instantiation of the new VC from your base VC. Since this is a custom object you could use NSData to archive, save it and then unarchive and use it in your new VC. http://stackoverflow.com/questions/29986957/save-custom-objects-into-nsuserdefaults – Munib May 18 '17 at 16:34
  • If I understood correctly your question, you can do this in any view. if let currentUser = FIRAuth.auth()?.currentUser { let email = currentUser.email // get more user data } – Mago Nicolas Palacios May 18 '17 at 16:35
  • Most of the developers use `UserDefaults` to save and get user data because it is extremely easy way. If you want to save user credentials at more secure place, use `KeyChain`. – ranjit.x.singh May 18 '17 at 16:48
  • Thanks @MagoNicolasPalacios that's exactly what I was looking for. – RPatel99 May 21 '17 at 20:42
  • No problem, I post it as an Answer for you to mark it as resolved. – Mago Nicolas Palacios May 22 '17 at 02:09

2 Answers2

2

There are multiple ways to use same user data or fetched data across multiple classes. It depends on the size and usage of data.

Here are some simple ways to achieve this:

  1. You can use UserDefaults to persist data across multiple classes even after restarting the app, data will persists after restarting until you clear it.

  2. You can use a Singleton class just like the AppDelegate, add some relevant properties e.g. Dictionary or Array and access it from any of the class.

  3. Pass data from one class to another when pushing the ViewController.

I think using a Singleton class would be enough solution for your problem if you don't need to persist it. And you can also write common methods in that Singleton class so you won't need to re-write the same method to use in multiple classes over and over again. Same goes for common Static Strings or Macros.

Hope it helps.

Bilawal Baig
  • 332
  • 1
  • 6
1

You can do this in any view. if let currentUser =

FIRAuth.auth()?.currentUser { 
let email = currentUser.email // 
get more user data 
}
Mago Nicolas Palacios
  • 2,501
  • 1
  • 15
  • 27