Инициализируйте переменные с данными Firebase в приложении SwiftUI - PullRequest
0 голосов
/ 10 апреля 2020

это мой первый раз программирование в Swift / SwiftUI, и я застрял с проблемой в течение последних нескольких недель.

Приложение Я пытаюсь создать приложение, в которое пользователи вводят данные для игры, эти данные сохраняются на их телефоне, и как только ответы становятся доступны в базе данных Firebase, они будет сравнивать с ними и рассчитывать балл.

До сих пор я был в состоянии: - Интегрировать FireBase в приложение iOS - Я был в состоянии запускать списки / циклы foreach для информации, собранной из базы данных

На данный момент Моя проблема заключается в следующем: я пытаюсь загрузить информацию из firebase, а затем использовать эту информацию для сравнения с пользовательскими данными и расчета балла. Когда я делаю это, функция, которая возвращает данные из firebase, возвращает пустой массив.

Функция результатов Firebase

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)
                }
            }
        }
    }

Если я запускаю этот код в представлении SwiftUI без вычислений, он извлекает и правильно отображает данные, вот пример представления, в котором работает правильно

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()
    }
}

Но в другом представлении я пытаюсь вычислить оценку пользователя в фоновом режиме, чтобы обновить профиль пользователя с правильной оценкой, я пробовал различные способы сделать это, но исходный массив всегда получается пустым.

Ниже приведен пример кода, который я пытаюсь запустить


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

        }
}

Любая помощь или руководство с этим очень ценится, Даниэль

Ответы [ 3 ]

1 голос
/ 10 апреля 2020

Исходя из данных, полученных от workingdog, я смог получить работающий код с незначительным изменением при вызове функции

Получить результаты функции

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")
    }
}

но мне пришлось изменить вызов функции следующим образом:

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

Спасибо за помощь!

0 голосов
/ 10 апреля 2020

, чтобы решить вашу проблему, вы можете попробовать что-то вроде этого:

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()
    }
}

, а затем назвать это так:

session.getResults() {
    // now do something with eventResults
}
0 голосов
/ 10 апреля 2020

Проблема, на мой взгляд, заключается в том, что в EventList (и везде) вы вызываете self.getFirebaseData (), который вызывает getResults (), и это асинхронный вызов. Вы должны подождать, пока он не закончится, прежде чем вы сможете получить:

var testvar2 = self.session.eventResults
...