실행하는 방법을 Firestore 쿼리 안쪽 지도에서 기능 스위프트

0

질문

나는 새로운 SwiftUI 및 중포 기지를 구축 내 첫 번째 응용 프로그램입니다. 나는 저장하는 게임에서 문서를 Firestore 고 필드 중 하나는 배열을 포함하는 사용자의 id 당신의 이미지를 볼 수 있습니다.

게임 데이터 구조

그는 말했다,내가 하려고 목록은 모든 게임의 주어진 사용자는 모든 플레이어에 나열된 각각의 세포(순서가 중요합니다).

을 만들기 위해 게임의 목록 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 또는 스 그때 나는 좋은 당신이 첫째 손잡이에 이 기능을 사용하여 기본적인 구문입니다. 당신은 편안의 기능과 비동기를 반복한 다음이 refactoring 코드를 사용하여 더 진보된 구문처럼,당신은 여기에.

귀하의 함수에 필요한 수행 비동기 일 이내에 각 루프 반복(각각의 문서). 당신이 실제로 이 작업을 수행할 필요가 두 번,비동기업 내에서 루프에서 반복입니다. 야 이것은 당신이 정말 하고 싶기 전에 진행하기 때문에 있을 수 있습 청소 방법을 포함할 수 있는 더 효율적인 NoSQL 에 데이터가 포함됩니다. 에 관계없이,의 목적을 위해 이 기능으로 시작하는 가장 기본적인 구문가를 위한 일하는 디스패치 그룹과 함께한다. 가 둥지를 이러한 때까지 당신은 그것을 작동하고 다음을 고려 refactoring.

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ý
..................................................................................................................