0

I am reading data from Firebase Database in Swift, then want to use length in later in function, however I lost the assignment done in with: closure. AKA the two print(length!) print different values. How can I remember this assignment whether it be a workaround to closures in Swift or way to save save value with a Firebase call.

var length:Int? = 1
        ref.child("Config").observeSingleEvent(of: .value, with: { (snapshot) in
                let value = snapshot.value as? NSDictionary
                length = (value?["AcademicBuildingsLength"] as? Int ?? 0)
                print(length!)
            })
        print(length!)
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • 1
    Firebase closures are asynchronous and the values are only valid within the closure. You could store the value as a class var; or leverage a completion handler to pass the value back to a calling function. See [this answer](https://stackoverflow.com/questions/42464237/make-code-with-firebase-asynchronous) and then my answer to [this question](https://stackoverflow.com/questions/60142804/what-does-the-snapshot-observer-code-do-in-firebase/60195689#60195689) – Jay Feb 16 '20 at 14:37

1 Answers1

0

To use your length property in the same class, just declare it in the class like so:

var length: Int?

override func viewDidLoad() {
    //...
}

To use your length property in other classes, consider making the property global:

public struct GlobalProperties {

    static var length: Int?

}

Assign value in closure:

ref.child("Config").observeSingleEvent(of: .value, with: { (snapshot) in
            let value = snapshot.value as? NSDictionary
            length = (value?["AcademicBuildingsLength"] as? Int ?? 0)

            // Assign value to length property
            self.length = length //if value is used within this class
            GlobalProperties.length = length //if value is used elsewhere
        })

Btw. The reason your print statements prints different values is because the bottom print is executed before the asynchronous firebase function is finished. You should grab the length value only inside the closure.

Dan Abnormal
  • 1,188
  • 11
  • 21
  • I believe this answer is suggesting to use a Singleton Design Pattern. With Swift, there are usually much more elegant options than Singletons - while they have their use, if used improperly they can cause memory issues and strong references. A class level var would probably be better suited here but also delegate functions, completion handlers (callbacks) and segues may fit the bill a bit better as all of those would maintain a weak reference to the var so it could be disposed of. This is a good read [Are singletons bad](https://cocoacasts.com/are-singletons-bad/) – Jay Feb 19 '20 at 17:55