3

I am trying to retrieve a string value from Firebase in order to get each username with an unique UID that is passed to the function, which returns the username of the user. However - since the firebase ObserveEvent is in closures, I can't return any value back because the actions happens asynchronous(?). I was wondering if it was a way of accomplishing this?

The function looks like this:

func GetUsername(uid:String) -> String {
    var username = String()
    firebase.child("Users").child(uid).observeSingleEventOfType(.Value) { (snapshot:FIRDataSnapshot) in

        username = snapshot.value!["Username"] as! String

    }

    return username
}

Obviously this doesn't work, but I want to be able to get the data by doing a GetUsername("whatevertheidmightbe"). Ideas?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
askaale
  • 1,199
  • 1
  • 23
  • 50
  • Just add a completion handler – Leo Dabus Jul 16 '16 at 08:52
  • @LeoDabus Like this? func GetUsername(uid:String, callback: (String) -> String) { firebase.child("Users").child(uid).observeSingleEventOfType(.Value) { (snapshot:FIRDataSnapshot) in callback(snapshot.value!["DisplayName"] as! String) } } I can't really make it work, somehow.. – askaale Jul 16 '16 at 09:00
  • Possible duplicate of [Using Firebase observeSingleEventOfType synchronously](http://stackoverflow.com/questions/38240294/using-firebase-observesingleeventoftype-synchronously) – adolfosrs Jul 16 '16 at 13:50
  • 2
    Possible duplicate of [Returning method object from inside block](https://stackoverflow.com/questions/22267865/returning-method-object-from-inside-block) – jscs Sep 07 '17 at 12:39

1 Answers1

8

You need to create completion handler like this

func GetUsername(uid:String , completion: (String) -> ()) {
    firebase.child("Users").child(uid).observeSingleEventOfType(.Value) { (snapshot:FIRDataSnapshot) in
    if let username = snapshot.value!["Username"] as? String
        completion(username)
    }
    else {
        completion("")
    }
}

And call function like this way

self.GetUsername(str) { (name) -> () in
    if name.characters.count > 0 {
         print(name)
    }
    else {
         print("Not found")
    }
}
Nirav D
  • 71,513
  • 12
  • 161
  • 183
  • Thank you so much. One more question; would it be possible to make it a return type of String? (So I can easily call GetUsername and retrieve the username in a string format? – askaale Jul 16 '16 at 09:18
  • Yes, I know - but I was just asking if it was possible to make the return type of type String? As I can see that right now it is of Void(). I don't have much experience with closures, so for all I know this might also be impossible..? – askaale Jul 16 '16 at 09:27
  • @askaale I have edited answer now you get batter idea about remove `void` so you can clearly understand it. Here we are passing the string value in completion handler. – Nirav D Jul 16 '16 at 09:31
  • Yeah, as far as I am concerned - you can't return a value of type string (in return name) format? – askaale Jul 16 '16 at 09:45
  • At least I can't, while trying to print it in the console (without printing it from the function, but using return instead). – askaale Jul 16 '16 at 09:46
  • I don't understand what you try to say. – Nirav D Jul 16 '16 at 09:47
  • What I basically mean is that instead of having to call a function and make it print the value, I want to make it a return type - to immediately return the string, instead of having to call it like a function, and and then print the value. Like (uid:String) -> String, and obtain the username by doing GetUsername("uid") (which returns just a string. – askaale Jul 16 '16 at 09:52
  • This is not possible and answer of this question you have already given because of async behaviour of firebase. – Nirav D Jul 16 '16 at 09:54
  • yeah okay - I just wanted to be 100% sure. Thank you very much for your help. I accepted your answer now. – askaale Jul 16 '16 at 09:55