-1

I have a View Controller that attempts to call a method from my UserModel class which gets a user document and fits the return data into a User structure. However, it is telling me it unexpectedly finds nil when unwrapping an optional value.

My UserModel:

class UserModel {
    var user:User?

    func getUser(userId: String) -> User? {
        let docRef = Firestore.firestore().collection("Users").document(userId)
        // Get data
        docRef.getDocument { (document, error) in
            if let document = document, document.exists {
                var user:User = User(name: document["name"] as! String, phone: document["phone"] as! String, imageUrl: document["imageUrl"]  as! String)
            } else {
                print("Document does not exist")
            }
        }
        return user!
    }
}

My Structure:

struct User {
    var name:String
    var phone:String
    var imageUrl:String
}    

My ViewController:

override func viewDidLoad() {
    super.viewDidLoad()
    userId = Auth.auth().currentUser?.uid
}

override func viewDidAppear(_ animated: Bool) {  
    let model = UserModel()
    user = model.getUser(userId: userId!)
    print(user?.name) 
}

The method runs fine when it is inside my View Controller, so I know it's getting the uid, the database call works, and the values all exist. I have printed them all separately. However, within its own class it doesn't work.

Any ideas?

Roman Podymov
  • 4,168
  • 4
  • 30
  • 57
Tai_
  • 19
  • 5

1 Answers1

0

It looks like getDocument is an async function. Hence, you should make getUser async:

func getUser(userId: String, completion: @escaping (User?) -> Void) {
    let docRef = Firestore.firestore().collection("Users").document(userId)   
    // Get data
    docRef.getDocument { (document, error) in
        if let document = document, document.exists {
            let user:User = User(name: document["name"] as! String, phone: document["phone"] as! String, imageUrl: document["imageUrl"] as! String)
            completion(user)
        } else {
            completion(nil)
        }
    }
}

This is how you should call it:

let model = UserModel()
model.getUser(userId: userId!) { user in
    print(user?.name)
}
Roman Podymov
  • 4,168
  • 4
  • 30
  • 57