Cum de a rula un Firestore interogare în interiorul o funcție de hartă în Swift

0

Problema

Sunt nou SwiftUI și Firebase și încerc să-mi construiesc primul meu app. Eu sunt stocarea Joc documente în Firestore și unul dintre câmpuri este o matrice care conține id-uri de utilizator de jucători, după cum puteți vedea în imagine.

Joc de structură de date

Acestea fiind spuse, eu sunt încercarea de a lista toate jocurile de un anumit utilizator și toți jucătorii enumerați în fiecare dintre celule (ordinea este importantă).

În scopul de a crea lista de jocuri în UI am creat un GameCellListView și o GameCellViewModel. La GameCellViewModel ar trebui să încarce ambele jocuri și matrice de utilizatori care corespund jucători din fiecare joc. Cu toate acestea nu sunt în măsură să se încarce utilizatorilor să o matrice. Trebuie sa treci prin jucatori matrice și interogare baze de date pentru fiecare Id-ul și pentru a adăuga un Utilizator matrice; apoi m-am ar trebui să fie capabil să se întoarcă acest Utilizator matrice. Din moment ce eu sunt, folosind-o pentru buclă, nu pot atribui valori la matrice și apoi se întoarce. Am încercat, folosind map(), dar nu pot efectua o interogare în interiorul de ea. Scopul este de a încărca că "toate" var cu o struct care primește un joc și jucătorii săi GamePlayers(players: [User], game: Game)

Acesta ar trebui să arate ceva de genul fragmentul de cod de mai jos, dar utilizatorii matrice vine mereu gol. Această funcție se execută pe GameCellViewModel init. Sper că puteți înțelege problema mea si va multumesc anticipat! A fost blocat pe acest timp de 2 săptămâni

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

Cel mai bun răspuns

0

Există o mulțime de piese în mișcare în cod și astfel să izoleze punctele de eșec ar necesita vedea codul adițional deci, doar să fie conștienți de faptul că, în avans. Asta a spus, dacă sunteți relativ nou pentru Firestore sau Swift atunci iti sugerez sa te mai întâi a obține un mâner pe această funcție, folosind sintaxa de bază. Odată ce sunteți confortabil cu intrarile si iesirile din asincron în buclă atunci aș sugera refactorizarea codului folosind mai avansate sintaxă, ca și cum ai avea aici.

Funcția necesită efectuarea asincron funcționează în fiecare buclă iterație (din fiecare document). De fapt, aveți nevoie pentru a face acest lucru de două ori, asincron funcționează într-o buclă într-o buclă. Fi sigur ca asta este ceea ce vrei cu adevărat să faci înainte de a trece pentru că nu poate fi curat moduri, care pot include un sistem mai eficient de arhitectura de date NoSQL. Indiferent, pentru scopuri de această funcție, începe cu cele mai de bază a sintaxei este pentru locuri de muncă, care este de Expediere Grup în comun cu for-loop. Du-te și cuibul ei până l-au de lucru și apoi ia în considerare 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)
        }
    }
}

De asemenea, am observat că în cel de-al doilea set de sarcini asincron în cea de-a doua buclă, adăugați instantaneu ascultători. Ești sigur că vrei să faci asta? Nu ai nevoie doar de un simplu document obține?

2021-11-23 16:44:21

Multumesc pentru ajutor! Voi pune în aplicare acest lucru în câteva ore și verificați dacă acesta funcționează pentru mine. Am folosit dispecerizare grupuri după ce și-a înghețat aplicația, dar nu a fost ușor diferită de sugestia ta. Ai putea oferi "corect" mod de a face acest lucru? Chiar dacă este nevoie de schimbarea structurii de date. Pot să includă mai mult cod, astfel încât să puteți avea o mai bună înțelegere. Multumesc din nou!
Álvaro Miguel Samagaio

În alte limbi

Această pagină este în alte limbi

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