0

this is my first time programming in Swift/SwiftUI and I have been stuck with an issue for the past couple of weeks.

The App I am trying to build an application in which users enter data for a game, this data is stored on their phone, and once the answers are available in a firebase data base it will compare against them and calculate a score.

So far I have been able to: - Integrate firebase into the iOS app - I have been able to run lists / foreach loops on the information gathered from the database

At the moment my issue is the following: I am trying to load the information from firebase, and then use this information to compare against the user data and calculate a score. When I do this the function that returns data from firebase is returning an empty array.

Firebase results function

func getResults() {
        ref.child("eventResults").observe(DataEventType.value) { (snapshot) in
            self.eventResults = []
            for child in snapshot.children {
                if let snapshot = child as? DataSnapshot,
                    let event = EventResults(snapshot: snapshot) {
                    self.eventResults.append(event)
                }
            }
        }
    }

If I run that code in a SwiftUI view with no calculations it pulls and shows the data correctly, here is an example view that works properly

import SwiftUI

struct TestView: View {
    @ObservedObject var session = FirebaseSession()


    var body: some View {

        ZStack {
            Color.init(red: 221/255, green: 221/255, blue: 221/255)
                .edgesIgnoringSafeArea(.all)
            VStack {
                List{
                    //
                    ForEach(self.session.eventResults) { event in

                        HStack() {
                            Text(event.name)
                                .font(.system(size: 30))
                            Spacer()
                            Text("\(event.answer)")
                                .font(.system(size: 30))

                        }

                    }

                }.frame(width: UIScreen.main.bounds.width*0.9)
            }.onAppear() {
                self.getFirebaseData()
            }
        }
    }

    func getFirebaseData() {
        session.getResults()
    }
}

But in another view I am trying to calculate the user score in the background in order to update the user profile with the correct score, I have tried a variety of methods to do this but the initial array always comes up empty.

Below is the sample code I am trying to run


import SwiftUI
import CoreData

struct EventList : View {

    @Environment(\.managedObjectContext) var managedObjectContext
    @ObservedObject var session = FirebaseSession()

    @FetchRequest(entity: UserEvents.entity(),
                  sortDescriptors: [])

    var userEvents: FetchedResults<UserEvents>

    var body: some View {

        ZStack {
            Color.init(red: 221/255, green: 221/255, blue: 221/255)
                .edgesIgnoringSafeArea(.all)
            VStack {
                ScrollView {
                    VStack(alignment: .leading) {
                        ForEach(userEvents) { eventVar in
                                EventCard(eventVar: eventVar)
                                    .cornerRadius(0)
                                    .shadow(color: .black, radius: 5, x: 2, y: 2.0)
                                    .padding(.horizontal)
                                    .frame(width: UIScreen.main.bounds.width)
                        }
                    }
                }
            }
        }.onAppear{
            self.getFirebaseData()
            var testvar2 = self.session.eventResults // is empty
            self.calcScores(resultlist: self.session.eventResults)
        }
    }

    //MARK: calculate Scores

    func getFirebaseData() {
        session.getResults()
    }



    func calcScores(resultlist: [EventResults]) {
          var testcount = resultlist.count // is empty

        }
}

Any help or guidance with this is greatly appreciated, Daniel

3 Answers 3

1

Based on the input from workingdog, I was able to get the code working with a minor variation on the function call

Get Results Function

func getResults(completion: @escaping (_ message: String) -> Void) {
    ref.child("eventResults").observe(DataEventType.value) { (snapshot) in
        self.eventResults = []
        for child in snapshot.children {
            if let snapshot = child as? DataSnapshot,
                let event = EventResults(snapshot: snapshot) {
                self.eventResults.append(event)
            }
        }
       completion("DONE")
    }
}

but I had to modify the function call to the following:

       session.getResults(completion: { message in
               print(message)
// code execution here
        })

Thanks for all the help!

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

Comments

0

The problem as I see it, is in EventList (and everywhere else) you call self.getFirebaseData() which calls getResults() and that is an asynchronous call. You have to wait till it is finished before you can have:

var testvar2 = self.session.eventResults

Comments

0

to fix your problem you could try something like this:

func getResults(completion: @escaping () -> Void) {
    ref.child("eventResults").observe(DataEventType.value) { (snapshot) in
        self.eventResults = []
        for child in snapshot.children {
            if let snapshot = child as? DataSnapshot,
                let event = EventResults(snapshot: snapshot) {
                self.eventResults.append(event)
            }
        }
       completion()
    }
}

then call it like this:

session.getResults() {
    // now do something with eventResults
}

3 Comments

Thanks! I am going to try this to see if it solves my issue, will be back with an answer.
So this partly worked. The function now returns a value and lets me use it for calculations, but it is only storing the first value of the array/dictionary.
I realized the completion() calls were not in the right place soon after I posted. Anyhow, I'm glad you got it to work.

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.