Firestore getDocument не работает должным образом - PullRequest
0 голосов
/ 12 апреля 2020

Я пытаюсь получить документ из базы данных Firestore и отфильтровать возвращенные данные по тому, что выбрал пользователь. Если пользователь выбирает ["snapchat", "facebook"], то я пытаюсь получить только эти указанные c значения из базы данных. Должен вернуть ["snapchat": username, "instagram": username, "UID": user UID]. Однако, когда я распечатываю возвращаемое значение функции, она содержит только ключ-значение для «UID». Вот мой код:

func getMediaInfo(selected: [String]) -> Dictionary<String, String> {
    var mediaDict: [String: String] = [:]
    let db = Firestore.firestore()
    let docRef = db.collection("users").document(Auth.auth().currentUser!.uid)
    docRef.getDocument { (document, error) in
        if let document = document, document.exists {
            let dataDescription = document.data()
            for media in selected {
                print(media, ":", dataDescription![media]!)
                mediaDict[media] = (dataDescription![media]! as! String)
            }
        } else {
            print("Document does not exist")
            self.dismiss(animated: true, completion: nil)
        }

    }
    mediaDict["UID"] = Auth.auth().currentUser?.uid
    print("Dictionary: ", mediaDict)
    return mediaDict
}

Мой вывод:

Dictionary: ["UID": "ub8bUMYBbeSPXd8UOdJWKCnbQzJ2"]
Twitter : nrjfjfj
Phone Number : nrnrjrn
Snapchat : hello

Как видите, значения извлекаются и выводятся правильно. Тем не менее, mediaDict при возврате имеет только пару значений ключа для «UID». Также кажется, что функция возвращается до заполнения всего словаря. Я не уверен, почему это произошло, и я не уверен, как я могу это исправить.

1 Ответ

1 голос
/ 12 апреля 2020

Данные загружаются из Firestore (и большинства современных веб- и облачных API) асинхронно. К моменту запуска return mediaDict, mediaDict[media] = (dataDescription![media]! as! String еще не был вызван, поэтому вы не видите его содержимого.

Любой код, которому нужны данные из базы данных, нуждается в быть внутри замыкания / обратного вызова или быть вызванным оттуда. Например:

docRef.getDocument { (document, error) in
    var mediaDict: [String: String] = [:]
    mediaDict["UID"] = Auth.auth().currentUser?.uid
    if let document = document, document.exists {
        let dataDescription = document.data()
        for media in selected {
            print(media, ":", dataDescription![media]!)
            mediaDict[media] = (dataDescription![media]! as! String)
        }
    } else {
        print("Document does not exist")
        self.dismiss(animated: true, completion: nil)
    }
    print("Dictionary: ", mediaDict)
}

Вы заметите, что здесь нет оператора return, поскольку вы не можете вернуть то, что еще не загружено.


альтернативой наличию кода внутри замыкания / обратного вызова является передача собственного обработчика завершения в getMediaInfo и вызов его после загрузки данных (где у нас теперь print("Dictionary: ", mediaDict)).

Это выглядело бы примерно так:

func getMediaInfo(selected: [String], completionHandler: (Dictionary<String, String>) -> ()) {
    let db = Firestore.firestore()
    let docRef = db.collection("users").document(Auth.auth().currentUser!.uid)
    docRef.getDocument { (document, error) in
        var mediaDict: [String: String] = [:]
        mediaDict["UID"] = Auth.auth().currentUser?.uid
        if let document = document, document.exists {
            let dataDescription = document.data()
            for media in selected {
                print(media, ":", dataDescription![media]!)
                mediaDict[media] = (dataDescription![media]! as! String)
            }
        } else {
            print("Document does not exist")
            self.dismiss(animated: true, completion: nil)
        }
        completionHandler(mediaDict)
    }
}


getMediaInfo(["one", "two"]) { info in
    print(info)
}

Вы заметите, что это очень похоже на то, что используют сами API-интерфейсы Firestore, вы просто возвращаете более специфичную для приложения версию c data.

См. также:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...