0

我正在尝试创建一个运行 Firebase 请求并将结果保存在变量中的类。然后从不同的视图访问变量。每个变量将用于一个类别。

我在与应用程序中显示数据的视图相同的视图中创建了一个类,并且它正在工作。但是当我将它移动到一个单独的 swift 文件时,它会给出以下错误:

struct ContentView: View {
    var body: some View {
        Home()

    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}


struct Home : View {
    @ObservedObject var categories = getCategoriesData()

    var body: some View { 
// Error: Unable to infer complex closure return type; add explicit type to disambiguate
        VStack {
            List(categories.datas) { i in
                Text(i.name)
            }
        }

    }
}

斯威夫特文件:

class getCategoriesData : ObservableObject {
    @Published var datas = [category]()

    init () {
        let db = Firestore.firestore()

        db.collection("ingredients").addSnapshotListener{ (snap, err) in

            if err != nil {
                print((err?.localizedDescription)!)
                return
            }
            for i in snap!.documentChanges {
                let id = i.document.documentID
                let name = i.document.get("name") as! String

                self.datas.append(category(id: id, name: name))
            }
        }


    }
}

struct category : Identifiable {
    var id : String
    var name : String


}

为了清楚起见,现在我正在从ingredientsFirebase 中的类别获取数据,在这种情况下,我想重新运行该类并将每个类别结果存储在一个数组/映射datas中,以便我可以在不同的视图中访问它们。或者将它放在不同的类中,因此对于每个视图,我运行数据库请求并获取其中一个类别的数据。

知道如何使它工作吗?

谢谢

4

1 回答 1

1

我能够编译您的代码,但预览窗格说它无法呈现视图,因为编译器崩溃了。

您的代码的主要问题似乎是数据访问代码在您的初始化程序中。我不建议这样做。相反,将这段代码提取到一个方法fetchData中,并在您的视图出现后调用该方法。例如像这样:

import SwiftUI
import Firebase

struct ContentView: View {
  var body: some View {
    Home()
  }
}

struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView()
  }
}


struct Home : View {
  @ObservedObject var viewModel = CategoryViewModel()

  var body: some View {
    VStack {
      List(viewModel.categories) { category in
        Text(category.name)
      }
      .onAppear() {
        self.viewModel.fetchData()
      }
    }
  }
}
import Foundation
import FirebaseFirestore

struct Category : Identifiable {
  var id : String
  var name : String
}

class CategoryViewModel: ObservableObject {
  @Published var categories = [Category]()

  func fetchData() {
    let db = Firestore.firestore()

    db.collection("ingredients").addSnapshotListener{ (snapshot, err) in
      guard let documents = snapshot?.documents else {
        print("No documents")
        return
      }
      self.categories = documents.map { documentSnapshot in
        let id = documentSnapshot.documentID
        let name = documentSnapshot.get("name") as! String
        return Category(id: id, name: name)
      }
    }
  }
}

您会注意到我还清理了命名(我建议阅读Ray WenderlichGoogle Swift 样式指南),并将您的映射代码转换为 a map- 这使事情更容易阅读,也更安全一些。

至于您关于如何订阅多个集合的问题,我建议为每个具有语义意义的视图使用专用的视图模型。

于 2020-05-12T08:54:23.517 回答