-2

I have an problem that I can not solve. A lot of questions are in JS and I don't really understand them.

I'm using Firebase as my database for my IOS app and Swift. Here is my situation:

I have a class file that contains functions that can retrieve values in my database. I'm calling these functions in some viewControllers.

The values retrieved by these functions are immediately used in these viewControllers.

My problem is that my app crash because of nil values returned by the class file functions. This happen because of the asynchronous Firebase snapshot.

The variables assumed to contain the values are used before their value is assigned => My app crash, or printed values are nil.

Then my question is simple: How can I structure my code to avoid this issue? I already tried completions, but that's not working for me: functions are still asynchronous.

Here is one of my function in the class file:

func initAverageMark(completionHandler: @escaping (_ mark: Double) -> ()) {

    let userRef = ref.child("users").child((user?.uid)!).child("mark")

    userRef.observeSingleEvent(of: .value, with: { (snapshot) -> Void in
        if let mark: Double = snapshot.value as? Double {
            completionHandler(mark)
        }
    }) { (error) in
        print(error.localizedDescription)
    }
}

One of my viewController code:

private var totalAsks: Double!

override func viewDidLoad() {
    super.viewDidLoad()

    initInfos()
}

func initInfos() {
    mainUser().initTotalAsks{ total in
        self.totalAsks = total
}
    initLabels()
}

func initLabels() {
    totalAsksLabel.text = " \(totalAsks!)" // it crashs here
}
AL.
  • 36,815
  • 10
  • 142
  • 281

1 Answers1

0

Assuming you'd want to set some label or something in your viewController to the value of mark you'd do it like this.

mainUser().initTotalAsks { mark in
    self.totalAsksLabel.text = " \(mark)"
}

Edit

Or if you absolutely want to use that Double.

private var totalAsks: Double? = nil {
    didSet {
        initLabels()
    }
}

override func viewDidLoad() {
    super.viewDidLoad()

    initInfos()
}

func initInfos() {
    mainUser().initTotalAsks{ total in
        self.totalAsks = total
    }
}

func initLabels() {
     guard totalAsks != nil else {
         return
     }
     totalAsksLabel.text = " \(totalAsks!)"
}