Craig.Pearce
Craig.Pearce

Reputation: 746

Retrieving child values from Firebase

I have a query the looks for a specific UUID and returns the object.

print(snapshot)  
Snap (users) {
"-KENROf9kGUPw1j6ghFo" =     {
    UUID = "A1166D66-31B4-4B1C-B28C-58E9E5615D16";
    nickname = Craig;
};
}

I'm trying to extract the nickname but having trouble.

Here is my query let queryRef = Firebase(url:"https://<url>.firebaseio.com/users")

And here is the query reference.

var handle = queryRef.queryOrderedByChild("UUID").queryEqualToValue("A1166D66-31B4-4B1C-B28C-58E9E5615D16").observeSingleEventOfType(.Value, withBlock: { snapshot in
        if snapshot.value is NSNull {
            print("snapshot empty")
        } else {
            print(snapshot) //this prints the snapshot above
            self.nickname = snapshot.value.objectForKey("nickname") as! String  //this returns an error
            print(self.nickname)
        }
    })
}

The self.nickname.... line returns the following error.

fatal error: unexpectedly found nil while unwrapping an Optional value I've tried a few different ways of structuring this, but have not yet found a way that doesn't fail.

Upvotes: 0

Views: 1228

Answers (2)

pkacprzak
pkacprzak

Reputation: 5629

Replace this line:

self.nickname = snapshot.value.objectForKey("nickname") as! String

with the following:

self.nickname = snapshot.value["nickname"] as! String

And make sure that your snapshot is an object with a property "nickname"

Upvotes: 0

Frank van Puffelen
Frank van Puffelen

Reputation: 598827

You're storing the users under a push id and then querying them by their uid. That's a bad idea. Instead, store the users under their uid (or in your case UUID) as this sample from the Firebase documentation on storing user data shows:

ref.authUser("[email protected]", password:"correcthorsebatterystaple") {
    error, authData in
    if error != nil {
        // Something went wrong. :(
    } else {
        // Authentication just completed successfully :)
        // The logged in user's unique identifier
        println(authData.uid)
        // Create a new user dictionary accessing the user's info
        // provided by the authData parameter
        let newUser = [
            "provider": authData.provider,
            "displayName": authData.providerData["displayName"] as? NSString as? String
        ]
        // Create a child path with a key set to the uid underneath the "users" node
        // This creates a URL path like the following:
        //  - https://<YOUR-FIREBASE-APP>.firebaseio.com/users/<uid>
        ref.childByAppendingPath("users")
           .childByAppendingPath(authData.uid).setValue(newUser)
    }
}

If you insist sticking to your current data structure, you'll need to handle the fact that a .Value query returns a list of children. Even if there's only one item that matches the query condition, it will still be a list of one item.

var query = queryRef.queryOrderedByChild("UUID").queryEqualToValue("A1166D66-31B4-4B1C-B28C-58E9E5615D16")
query.observeSingleEventOfType(.Value, withBlock: { snapshot in
    if snapshot.value is NSNull {
       print("snapshot empty")
    } else {
        for child in snapshot.children {
            self.nickname = child.value.objectForKey("nickname") as! String
            print(self.nickname)
        }
    }
})

Upvotes: 1

Related Questions