Archie Gertsman
Archie Gertsman

Reputation: 1661

Swift closure not setting variable

I'm trying to set a variable that is outside a closure inside that closure, but it doesn't end up getting set in the end. However, the value that I'm setting the variable to is being printed to the console. Also, right after setting the return variable and printing it itself, the correct value is being printed to the console. The problem arises when I return the variable; its value stays the same as the value at initialization. Here is some psuedo-code:

let str: String = {
    var ret: String = "default value"

    functionWithClosure(with: (some_name) in {
        if let name = some_name {
            ret = name
            print(name) // prints successfully
            print(ret_name) // also prints successfully
        }
    })

    return ret // returns "default value"
}()

This is the actual code that isn't working:

let name: String = {
    var ret_name = "default value"

    if let uid = FIRAuth.auth()?.currentUser?.uid {
        FIRDatabase.database().reference().child("users").child(uid).observeSingleEvent(of: .value, with: { (snapshot) in
            if let dictionary = snapshot.value as? [String: AnyObject] {
                if let name = dictionary["name"] as? String {
                    ret_name = name
                    print(ret_name)
                }
            }
        })
    }

    return ret_name
}()

Upvotes: 0

Views: 741

Answers (2)

Nishant Bhindi
Nishant Bhindi

Reputation: 2252

May be below can be the workout for the issue.

func getName(completion: @escaping(_ name: String) -> Void) {
if let uid = FIRAuth.auth()?.currentUser?.uid {
    FIRDatabase.database().reference().child("users")
    .child(uid).observeSingleEvent(of: .value, with: { (snapshot) in
    if let dictionary = snapshot.value as? [String: AnyObject] {
        if let name = dictionary["name"] as? String {
            completion(name)
        }
    }
})
}

Now set the value of string by below code

getName(completion: { name in 
     let str = name
 })

Upvotes: 1

Vlad Pulichev
Vlad Pulichev

Reputation: 3272

.observeSingleEvent is working async.

You can do something like this:

func getRetname(completion: @escaping(_ retName: String) -> Void) {
    if let uid = FIRAuth.auth()?.currentUser?.uid {
        FIRDatabase.database().reference().child("users").child(uid).observeSingleEvent(of: .value, with: { (snapshot) in
        if let dictionary = snapshot.value as? [String: AnyObject] {
            if let name = dictionary["name"] as? String {
                ret_name = name
                print(ret_name)
                completion(ret_name)
            }
        }
    })
}

Then, you can use it everywhere you want:

getRetname(completion: { ret_name in 
    // ret_name - your data
})

Hope it helps

Upvotes: 1

Related Questions