Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays init()中的Swift Array.append与Firestore(Google Cloud/FIrebase)组合不起作用_Arrays_Swift_Firebase_Google Cloud Firestore_Swiftui - Fatal编程技术网

Arrays init()中的Swift Array.append与Firestore(Google Cloud/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

我已经尝试了我的第一个SwiftUI项目。 我只想显示存储在Firestore(Google Firebase)中的一些数据。 这是我的密码:

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)