如何运行Firestore查询内部的一个地图的功能在迅速

0

的问题

我是新来的SwiftUI和火力地堡和我在试图建立我的第一个应用程序。 我储存游戏文件Firestore及的领域之一是一系列包含的用户标识的球员你可以看到的图像。

游戏数据结构

正在说,我想列举所有的游戏有一定的用户和拥有所有的球员中所列的每一个细胞(以是重要)。

为了创建该清单的游戏在UI我创建了一个GameCellListView和GameCellViewModel. 该GameCellViewModel应该载入这两个游戏和该阵列的用户对应的每一个的游戏。 但是我不能够载的用户的一个阵列。 我已经去过玩家阵列和查询的数据库对每个Id和追加的用户阵列;然后我应该能够返回这个用户阵列。 因为我使用一个循环,我不能分配的价值观的阵列,然后返回。 我试图使用地图(),但我不能进行查询。 我们的目标是要载荷,"所有"var有一个结构,收到一个游戏和玩家 GamePlayers(players: [User], game: Game)

它看起来应该是什么样的代码下面,但用户阵总是空的。 这个函数的运行GameCellViewModel init。 我希望你能了解我的问题,并感谢你在前进! 被困在这个为期2周的现在

func loadData() {
        let userId = Auth.auth().currentUser?.uid
        
        db.collection("games")
            .order(by: "createdTime")
            .whereField("userId", isEqualTo: userId)
            .addSnapshotListener { (querySnapshot, error) in
            if let querySnapshot = querySnapshot {
                self.games = querySnapshot.documents.compactMap { document in
                    do {
                        let extractedGame = try document.data(as: Game.self)
                        var user = [User]()
                        let users = extractedGame!.players.map { playerId -> [User] in

                            self.db.collection("users")
                                .whereField("uid", isEqualTo: playerId)
                            .addSnapshotListener { (querySnapshot, error) in
                                guard let documents = querySnapshot?.documents else {
                                    print("No documents")
                                    return
                                }
                                user = documents.compactMap { queryDocumentSnapshot -> User? in
                                    return try? queryDocumentSnapshot.data(as: User.self)
                                    
                                }
                            }
                            return user
                        }
                        
                        self.all.append(GamePlayers(players: users.first ?? [User](), game: extractedGame!))

                        
                        return extractedGame
                    }
                    catch {
                        print(error)
                    }
                    return nil
                }
            }
        }
    }
1

最好的答案

0

有很多运动部件在你的代码和所以隔离的故障点将需要看到额外的代码这样只是知道的,预付。 这就是说,如果你相对较新Firestore或Swift然后,我会强烈建议你第一次得到处理这种功能使用的基本法。 一旦你舒适的来龙去脉异步循环的话,我会建议重构的代码使用更先进的语法,就像你在这里。

你的功能需要,执行同步的工作在每个回路迭代(每个文件)。 实际上,你需要做这两次同步工作的一个循环内在的循环。 可以肯定这是你真正想要做之前进行,因为有可能更清洁的方式,其中可包括更有效的非sql数据架构。 无论如何,对于本功能,从最基本的语法存在的工作是派遣组与对环。 来吧,鸟巢这些直到你拥有了它的工作,然后考虑重构。

func loadData() {
    // Always safely unwrap the user ID and never assume it is there.
    guard let userId = Auth.auth().currentUser?.uid else {
        return
    }
    // Query the database.
    db.collection("games").whereField("userId", isEqualTo: userId).order(by: "createdTime").addSnapshotListener { (querySnapshot, error) in
        if let querySnapshot = querySnapshot {
            // We need to loop through a number of documents and perform
            // async tasks within them so instantiate a Dispatch Group
            // outside of the loop.
            let dispatch = DispatchGroup()
            
            for doc in querySnapshot.documents {
                // Everytime you enter the loop, enter the dispatch.
                dispatch.enter()
                
                do {
                    // Do something with this document.
                    // You want to perform an additional async task in here,
                    // so fire up another dispatch and repeat these steps.
                    // Consider partitioning these tasks into separate functions
                    // for readability.

                    // At some point in this do block, we must leave the dispatch.
                    dispatch.leave()
                } catch {
                    print(error)
                    
                    // Everytime you leave this iteration, no matter the reason,
                    // even on error, you must leave the dispatch.
                    dispatch.leave()
                    
                    // If there is an error in this iteration, do not return.
                    // Return will return out of the method itself (loadData).
                    // Instead, continue, which will continue the loop.
                    continue
                }
            }
            
            dispatch.notify(queue: .main) {
                // This is the completion handler of the dispatch.
                // Your first round of data is ready, now proceed.
            }
        } else if let error = error {
            // Always log errors to console!!!
            // This should be automatic by now without even having to think about it.
            print(error)
        }
    }
}

我还注意到,在第二组异步的任务在第二环,你在添加快照听众。 你真的确定你要这么做? 不你只是需要一个普通的文件得到什么?

2021-11-23 16:44:21

谢谢你的帮助! 我会实现这在几个小时,并检查它是否适用于我的。 我用分派团一旦它冻结的程序,但略有不同,从你的建议。 你能提供"正确的"的方式这样做? 甚至如果这需要改变数据结构。 我可以包括更多的代码,这样就可以有更好的理解。 再次感谢!
Álvaro Miguel Samagaio

其他语言

此页面有其他语言版本

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................