Arrays init()中的Swift Array.append与Firestore(Google Cloud/FIrebase)组合不起作用
我已经尝试了我的第一个SwiftUI项目。 我只想显示存储在Firestore(Google Firebase)中的一些数据。 这是我的密码:Arrays init()中的Swift Array.append与Firestore(Google Cloud/FIrebase)组合不起作用,arrays,swift,firebase,google-cloud-firestore,swiftui,Arrays,Swift,Firebase,Google Cloud Firestore,Swiftui,我已经尝试了我的第一个SwiftUI项目。 我只想显示存储在Firestore(Google Firebase)中的一些数据。 这是我的密码: import SwiftUI import FirebaseFirestore import FirebaseFirestoreSwift struct MonsterObj: Identifiable, Equatable, Hashable { var id = UUID() var name: String var ele
import SwiftUI
import FirebaseFirestore
import FirebaseFirestoreSwift
struct MonsterObj: Identifiable, Equatable, Hashable {
var id = UUID()
var name: String
var element: String
var immune: String
var size: String
var twoStarWeakness: String
var threeStarWeakness: String
#if DEBUG
static let exampleMonster = MonsterObj(id: UUID(), name: "Test Monster", element: "Test Element", immun: "Test immun", groesse: "Test groesse", twoStarWeakness: "Test 2 Weakness", threeStarWeakness: "Test3 Weakness")
#endif
}
class MonsterC: ObservableObject {
@Published var monsters = [MonsterObj]()
init() {
let db = Firestore.firestore()
var monsterNames: [String] = []
db.collection("Monster").getDocuments() { (querySnapshot, err) in
if let err = err {
print(err)
} else {
for document in querySnapshot!.documents {
monsterNames.append("\(document.documentID)")
print("document: \(document.documentID)")
}
}
}
for monsterName in monsterNames {
print(monsterName)
db.collection("Monster").document(monsterName).getDocument { (document, error) in
if let document = document, document.exists {
let elementGetter = document.get("element") as! String
let immuneGetter = document.get("immune") as! String
let sizeGetter = document.get("size") as! String
let twoStarWeaknessGetter = document.get("2 star weakness") as! String
let threeStarWeaknessGetter = document.get("3 star weakness")as! String
self.monsters.append(MonsterObj(name: monsterName, element: elementGetter, immune: immuneGetter, size: sizeGetter, twoStarWeakness: twoStarWeaknessGetter, threeStarWeakness: threeStarWeaknessGetter))
}
}
}
}
}
我的看法是:
import SwiftUI
struct ContentView: View {
@EnvironmentObject var monsterT: MonsterC
var body: some View {
List(monsterT.monsters, id: \.self) { monster in
Text(monster.name)
}
}
}
我对SceneDelegate.swift做了如下工作:
var window: UIWindow?
var monsterT = MonsterC()
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions {
// Create the SwiftUI view that provides the window contents.
let contentView = ContentView().environmentObject(monsterT)
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}
所以我的问题是列表是空的。
我发现在MonsterC类的init
中,monsterNames.append(“\document.documentID)”)一行不向monsterNames追加任何内容。
但是print(“document:\(document.documentID)”)
正在打印所有的名称
我的google Firestore结构如下所示:
Collection -> Document -> Fields
-------------------------------------------
Monster -> Anjanath -> immune: fire,
element: fire
等等。
只有一个集合(“怪物”)
有人能向初学者解释一下为什么这里没有使用.append
,但print做得很好吗?您需要了解调用异步函数。我的建议是重新构造代码,在init()中执行这些异步调用不是一个好主意
您的函数“db.collection(“Monster”).getDocuments(){(querySnapshot,err)位于…”
是异步的。您必须等到它完成后才能使用结果,或者在函数内部执行您需要的操作。注意,您还有另一个异步函数“db.collection(“Monster”).document(monsterName).getDocument{”
因此.append不起作用,因为在执行.append时,函数“db.collection(“Monster”).getDocuments(){(querySnapshot,err)in…”的结果不可用
因此,如果您必须使用此狡猾的代码,请尝试以下方法来解决阵列问题:
class MonsterC: ObservableObject {
@Published var monsters = [MonsterObj]()
init() {
let db = Firestore.firestore()
db.collection("Monster").getDocuments() { (querySnapshot, err) in
if let err = err {
print(err)
} else {
var monsterNames: [String] = []
for document in querySnapshot!.documents {
monsterNames.append("\(document.documentID)")
print("document: \(document.documentID)")
}
for monsterName in monsterNames {
print(monsterName)
db.collection("Monster").document(monsterName).getDocument { (document, error) in
if let document = document, document.exists {
let elementGetter = document.get("element") as! String
let immuneGetter = document.get("immune") as! String
let sizeGetter = document.get("size") as! String
let twoStarWeaknessGetter = document.get("2 star weakness") as! String
let threeStarWeaknessGetter = document.get("3 star weakness")as! String
self.monsters.append(MonsterObj(name: monsterName, element: elementGetter, immune: immuneGetter, size: sizeGetter, twoStarWeakness: twoStarWeaknessGetter, threeStarWeakness: threeStarWeaknessGetter))
}
}
}
}
}
}
}
您需要了解调用异步函数。我的建议是重新构造代码,在init()中执行这些异步调用不是一个好主意
您的函数“db.collection(“Monster”).getDocuments(){(querySnapshot,err)位于…”
是异步的。您必须等到它完成后才能使用结果,或者在函数内部执行您需要的操作。注意,您还有另一个异步函数“db.collection(“Monster”).document(monsterName).getDocument{”
因此.append不起作用,因为在执行.append时,函数“db.collection(“Monster”).getDocuments(){(querySnapshot,err)in…”的结果不可用
因此,如果您必须使用此狡猾的代码,请尝试以下方法来解决阵列问题:
class MonsterC: ObservableObject {
@Published var monsters = [MonsterObj]()
init() {
let db = Firestore.firestore()
db.collection("Monster").getDocuments() { (querySnapshot, err) in
if let err = err {
print(err)
} else {
var monsterNames: [String] = []
for document in querySnapshot!.documents {
monsterNames.append("\(document.documentID)")
print("document: \(document.documentID)")
}
for monsterName in monsterNames {
print(monsterName)
db.collection("Monster").document(monsterName).getDocument { (document, error) in
if let document = document, document.exists {
let elementGetter = document.get("element") as! String
let immuneGetter = document.get("immune") as! String
let sizeGetter = document.get("size") as! String
let twoStarWeaknessGetter = document.get("2 star weakness") as! String
let threeStarWeaknessGetter = document.get("3 star weakness")as! String
self.monsters.append(MonsterObj(name: monsterName, element: elementGetter, immune: immuneGetter, size: sizeGetter, twoStarWeakness: twoStarWeaknessGetter, threeStarWeakness: threeStarWeaknessGetter))
}
}
}
}
}
}
}
如果您打印print(“在monstersNames.append之后:\monsterNames)”
可能是因为您缺少asychrone概念吗?如果您打印print(“在monstersNames.append之后:\monsterNames)”)
这可能是因为您缺少asychrone概念吗?感谢您提供有关异步函数的信息。您称之为“危险代码”所以我想这样做是不好的。你能告诉我如何做得更好吗?很抱歉称代码不可靠。好问题,如何使代码更好。但是我无法理解你想要实现什么。对我来说init()用于创建/准备类和初始化任何存储的属性。要更新/填充属性,我倾向于在init()之外进行,尤其是在它涉及异步函数的情况下。类似于带回调的静态func createMonsterClass(…),以防在获取时出错。当您在init()中执行所有这些操作时你永远不知道在你想使用它的时候是否有错误或者对象是否准备好了。因为你已经导入了FirebaseFirestoreSwift
,你可以使用queryDocumentSnapshot.data(as:MonsterObj.self)
来简化映射,谢谢你提供了关于异步函数的信息。你称它为“危险代码”所以我想这样做是不好的。你能告诉我如何做得更好吗?很抱歉称代码不可靠。好问题,如何使代码更好。但是我无法理解你想要实现什么。对我来说init()用于创建/准备类和初始化任何存储的属性。要更新/填充属性,我倾向于在init()之外进行,尤其是在它涉及异步函数的情况下。类似于带回调的静态func createMonsterClass(…),以防在获取时出错。当您在init()中执行所有这些操作时您永远不知道是否存在错误或对象在您想要使用它时是否已准备就绪。由于您已导入FirebaseFirestoreSwift
,您可以使用queryDocumentSnapshot.data(as:MonsterObj.self)