0

I'm trying to get results from Firebase and put them into Array, but it seems I miss something. What I want is to get 'Time' and 'Blood Glucose" values from Firebase and to put them into an arrays which I will use for Charts. I'm able to put the data into 'BG' and 'TIME' arrays, but when I 'append' them into 'FetchedDate' and 'FetchedBG' I see empty arrays (FetchedBG and FetchedDate)

var FetchedDate:[String]! = []
var FetchedBG: [Double]! = []

//GET DATA FROM FB 
func GetDetails(){
    let posts = rootRef.child("Diary/\(userID!)/\(passedDATE!)")
    //let posts = rootRef.queryOrderedByChild(passedDATE!)
    posts.observeEventType(FIRDataEventType.Value , withBlock: { (snapshot) in

        for list in snapshot.children {
            if  let BG = list.value.objectForKey("Blood Glucose")!.doubleValue {
            self.FetchedBG.append(BG)
                print(BG) // SHOWS RESULTS AS EXPECTED
            }
            if let TIME = list.value.objectForKey("Time") {
            self.FetchedDate.append(TIME as! String)
                  print(TIME) // SHOWS RESULTS AS EXPECTED
            }
        }
    })  { (error) in
        print(error.localizedDescription)
    }
}

override func viewDidLoad() {
    super.viewDidLoad()

    GetDetails()

    print(FetchedDate) // EMPTY ARRAY 
    print(FetchedBG) // EMPTY ARRAY 

1 Answer 1

2

Firebase loads (and synchronizes) the data from your database asynchronously. Since that may take some time, your code continues executing and you print the arrays while they're still empty.

Once a value is available (either for the first time or when the data has changed), your block is invoked. It adds the data to the arrays. But by that time your print statements have long finished.

The solution is to move the code that needs to run when the value is available (or when it has changed) into the block. E.g.

var FetchedDate:[String]! = []
var FetchedBG: [Double]! = []

//GET DATA FROM FB 
func StartSynchronizingDetails(){
    let posts = rootRef.child("Diary/\(userID!)/\(passedDATE!)")
    //let posts = rootRef.queryOrderedByChild(passedDATE!)
    posts.observeEventType(FIRDataEventType.Value , withBlock: { (snapshot) in

        for list in snapshot.children {
            if  let BG = list.value.objectForKey("Blood Glucose")!.doubleValue {
            self.FetchedBG.append(BG)
                print(BG) // SHOWS RESULTS AS EXPECTED
            }
            if let TIME = list.value.objectForKey("Time") {
            self.FetchedDate.append(TIME as! String)
                  print(TIME) // SHOWS RESULTS AS EXPECTED
            }
        }
        print(FetchedDate)
        print(FetchedBG)
    })  { (error) in
        print(error.localizedDescription)
    }
}

override func viewDidLoad() {
    super.viewDidLoad()

    StartSynchronizingDetails()

This is a very common pattern when your app interacts with (potentially time-consuming) network resources. It is also precisely the reason Firebase's observeEventType takes a withBlock: argument: to isolate the code that starts synchronizing from the code that responds to value updates.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much! Now I can put the data into the chart :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.