在 SwiftUI 应用程序上使用 firebase 数据初始化变量

Posted

技术标签:

【中文标题】在 SwiftUI 应用程序上使用 firebase 数据初始化变量【英文标题】:Initialize variables with firebase data on SwiftUI app 【发布时间】:2020-04-09 21:24:58 【问题描述】:

这是我第一次使用 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

        

非常感谢任何帮助或指导, 丹尼尔

【问题讨论】:

【参考方案1】:

根据 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
        )

感谢大家的帮助!

【讨论】:

【参考方案2】:

我看到的问题是在 EventList(以及其他任何地方)中调用 self.getFirebaseData() 调用 getResults() 并且这是一个异步调用。 您必须等到它完成才能拥有:

var testvar2 = self.session.eventResults

【讨论】:

【参考方案3】:

要解决您的问题,您可以尝试以下方法:

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

【讨论】:

谢谢!我要试试这个,看看它是否能解决我的问题,会回来回答。 所以这部分工作。该函数现在返回一个值并让我将其用于计算,但它只存储数组/字典的第一个值。 我在发布后不久就意识到completion() 调用不在正确的位置。无论如何,我很高兴你让它工作。

以上是关于在 SwiftUI 应用程序上使用 firebase 数据初始化变量的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swiftui 上关闭应用程序时创建警报(不是通知)

是否可以使用 SwiftUI 在 TextField 上设置字符限制?

在 SwiftUI 中的特定页面上隐藏标签栏

SwiftUI:如何在 macOS 11 上设置工具栏的标题?

在 MacOS 上构建 SwiftUI “Hello World”

SwiftUI 2.0 在 macOS 上禁用窗口的缩放按钮