1

This Question is not a duplicate.

So I have a simple function that will take a parameter of the index of what tableview cell was clicked so the function will go into the didSelectRowAt tableView function, and it will also return a String.

The Function is called getOpposingUserName and it connects to firebase to gather the information provided inside the database.

Now I know that the functionality of the function works it is sort of a logic error that I don't quite understand. From what I know is that whenever you try to get data from firebase it runs that code and takes a second to actually get the data. but as its doing that it keeps running the code below where you tried to get data from the database.

which means if I want to return a String then the string will always be nil or whatever I set its initial value to, because the database will take to long to load and the function will already have ran through the code to return something.(that's my understanding of it, I'm sure there is a way more technical way to explain it)

so basically what I am asking is how would I "load" the data into a variable first then check that firebase has indeed loaded something into the variable and then return the variable for whatever called the function

This question IS not a duplicate I have read the question and tried to make sense of it in my own implementation. I am not returning a function that code is confusing to me when I read it.

here is my code for the function

func getOpposingUsername(_ index: Int) -> String {
        var opposingUser: String = ""
        //the self.tieBetToUser just gets the randomized id from the bet in firebase don't need to worry about it

self.datRef.child("Bets").child(self.tieBetToUser[index]).observe(.childAdded, with: { snapshot in
            guard let dict = snapshot.value as? [String: AnyHashable] else {
                return
            }

            opposingUser = dict["OpposingUsername"] as! String
            print(opposingUser) //this code actually never runs I found out




        })
        //sleep(4) this will not work and is actually bad code anyway different phones may be faster or slower
        return opposingUser // will always return "" at the moment

    }

here is the solution the internet has provided

typealias someting = (String?) -> Void
    func getOpposingUsername(completionHandler: @escaping someting, _ index: Int) {
        var opposingUser: String = ""
        self.datRef.child("Bets").child(self.tieBetToUser[index]).observe(.childAdded, with: { snapshot in


            guard let dict = snapshot.value as? [String: AnyHashable] else {
                return
            }

            opposingUser = dict["OpposingUsername"] as! String
            if opposingUser.isEmpty {
                completionHandler(nil)
            } else {
                completionHandler(opposingUser)
            }




        })


    }

How exactly would I call this function somewhere else? like getOpposingUsername(somethingGoesHere, index.path)

Devin Tripp
  • 115
  • 13
  • @Sneak read that question before I made this one does not explain anything well and doesn't answer my question – Devin Tripp Mar 28 '17 at 22:57
  • 1
    Read up about asynchronous programming in Swift. If you feel that the linked duplicates do not answer your question, please [edit] your post and provide additional details on why it doesn't. – JAL Mar 28 '17 at 22:58
  • 1
    @DevinTripp It does actually answer the question. You can see the other duplicate flag on that one too. You need create a **completionHandler** and wait for the firebase to "get your data" from the server before you call the completionHandler and return the string with your completionHandler as they provided in the example. –  Mar 28 '17 at 22:59
  • Use a closure. Look at the `completionHandler` in the linked question. – JAL Mar 28 '17 at 22:59
  • the second linked duplicate question does not relate to firebase – Devin Tripp Mar 28 '17 at 23:01
  • As I've said previously, the concept of asynchronous programming is agnostic to Firebase. Either way, the answer is the same. – JAL Mar 28 '17 at 23:02
  • @DevinTripp Here is a tutorial on what we are trying to explain. https://thatthinginswift.com/completion-handlers/ You can find more on google, Grasp the basics and you will see it doesnt matter where you use it as Jal said. –  Mar 28 '17 at 23:04
  • also I have a parameter they don't So would I put the parameter in the typealias or would I keep it in the function, also how do I call this function do I just put dispatch.main or something? what do I put as the completion parameter when I call the function @Sneak – Devin Tripp Mar 28 '17 at 23:22
  • You can add any parameter you want to a completionBlock, it is up to you, you can add many parameters too not only one. You can end the completionBlock finish call it wherever you need to , inside dispatch or outside as you want. Read this question how to create a block and look on youtube/google for more examples. GL http://stackoverflow.com/questions/30401439/how-could-i-create-a-function-with-a-completion-handler-in-swift or here for complete tutorials https://www.youtube.com/results?search_query=swift+completion+handler –  Mar 28 '17 at 23:24
  • What would I do to call the function Here Ill post an answer that I have tried, nvm I'll Update the question. – Devin Tripp Mar 28 '17 at 23:28
  • @sneak How would I call the function what goes in the first parameter I updated the question to show the new function – Devin Tripp Mar 28 '17 at 23:37
  • @JAL can you show me how to call this or tell me what I am doing wrong I tried to call it but it doesn't return a String and I need it to return a String – Devin Tripp Mar 28 '17 at 23:58
  • @NiravD do you think you can help mate? Know anything about completion handlers? – Devin Tripp Mar 29 '17 at 00:57
  • @ForrestKunecke got any ideas? – Devin Tripp Mar 29 '17 at 00:59

0 Answers0