2

I'm trying to read user data from Firebase but the username variable is always nil.

let storage = Storage.storage()
let storageRef = storage.reference()
let userID = Auth.auth().currentUser?.uid
let canvasName = NSUUID().uuidString
var username: String? = nil

//get username
self.ref.child("Users").observeSingleEvent(of: .value, with: { (snapshot) in
    let usersProfile = snapshot.value as? NSDictionary
    let userProfile = usersProfile![userID!] as? NSDictionary
    username = userProfile!["Username"] as? String            
}) { (error) in
    print(error.localizedDescription)
}

//create new canvas
let canvasValue:[String:Any] = ["UserID":userID!,
                                "Username": username!,//always nil 
                                "TimeCreated": NSDate().timeIntervalSince1970,
                               ]
let canvasAutoID = self.ref.child("Users").child(userID!).child("Canvas").childByAutoId().key
    self.ref.child("Canvas").child(canvasAutoID!).setValue(canvasValue)

Here's an image of the firebase database.

image here

1
  • 1
    Looks like you're accessing username outside of the block; this is an asynchronous operation. Of course it's nil, it hasn't been set yet by the time it hits that line. Commented Dec 12, 2018 at 4:32

2 Answers 2

2

observeSingleEvent works asynchronously. It might have to make a network request to get that data, so the closure will run at some indeterminate time after the function is called. The code after it, where you try to access username, runs first, meaning username still has its initial value nil. You can fix this by moving your code inside the closure, as shown below, or by putting it in another function that you call from inside the closure.

//get username
self.ref.child("Users").observeSingleEvent(of: .value, with: { (snapshot) in
    let usersProfile = snapshot.value as? NSDictionary
    let userProfile = usersProfile![userID!] as? NSDictionary
    username = userProfile!["Username"] as? String 
    //create new canvas
    let canvasValue:[String:Any] = ["UserID":userID!,
                                    "Username": username!, 
                                    "TimeCreated": NSDate().timeIntervalSince1970,
                                   ]
    let canvasAutoID = self.ref.child("Users").child(userID!).child("Canvas").childByAutoId().key
    self.ref.child("Canvas").child(canvasAutoID!).setValue(canvasValue)          
}) { (error) in
        print(error.localizedDescription)
}
Sign up to request clarification or add additional context in comments.

Comments

1

You can get your username like below.

 self.ref.child("Users").observe(.value) { (snapshot) 
          if snapshot.childrenCount > 0 {
               for users in snapshot.children.allObjects as! [DataSnapshot] {  
                     let userObject = users.value as? [String: AnyObject]
                     let userName  = userObject?["Username"] as! String 
                     print(userName)
                }
            } else {
                print("No users")
            }
      }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.