首页 > 解决方案 > Firebase getDocument(querySnapshot)不起作用

问题描述

我正面临 Firebase 快照的问题。我成功地将我的 Fierbase 帐户与我的 Xcode 项目联系起来。我能够更改 Firestore 云中的数据。但我无法阅读。这是我的功能:


class UserService{
static func CheckIfMoreThanOneUserIsLoggedIn() -> Bool{
    var BoolenToReturn:Bool?
    let AuthUser = Auth.auth().currentUser
    let userId = AuthUser!.uid
    let localDeviceString = Constants.UserDefaultsStorage.string(forKey: userId)
    // LocalDeviceString is generated (20 random letters) when the user is logged in succesfully.
    //This DeviceString would be stored on one hand in the cloud on the other hand on the device.
    //When the user open the Application it checks if the localDeviceString of the cloud is the same as the String stored on the device.
    //I’m able to denie the user access through multiple devices simultaneously (-> Any imporvent is desired)
    let newUserReference = Firestore.firestore().collection("users").document(userId)
    newUserReference.getDocument {
        (querySnapshot, err) in // Code never runs the closure
        guard err != nil else {
            return
        }
        for document in querySnapshot!.data()! {
            if document.key == "RandomString" {
                let docValue:String = document.value as! String
                if docValue == localDeviceString{
                    BoolenToReturn = true
                }
                else{
                    BoolenToReturn = false
                }
            }
        }
    }

    return BoolenToReturn  ?? false
}
}

编辑

基于@Frank van Puffelen 的链接,我能够制定自己的解决方案。但是这个程序并没有我想要的那么专业,因为现在它是一个在LaunchViewController. 此外,我将 segueHomeViewController称为newUserReference.getDocument. 我不想实现的目标:在 UserService 类中定义的一个函数,如果允许用户使用该应用程序,它将返回一个布尔值。

标签: iosswiftfirebasegoogle-cloud-firestore

解决方案


我想你可能想调查一个完成处理程序。这个想法是调用一个异步函数,然后在该函数完成时执行一个任务。下面的代码几乎可以直接应用于您的问题的解决方案。

所以这是一个你可以开始的例子。假设我们有一个用户存储在用户集合中的应用程序

users
   uid_0
      name: "Steve"
   uid_1
      name: "Danno"
   uid_2
      name: "Junior"
   uid_3
      name: "Tani"

一个新用户想要注册,但该应用程序不允许重复名称。因此,我们需要查询我们的 users 集合以确定该名称是否已被使用。这是调用查询函数的代码。

self.doesUserNameExist(userName: "Steve" ) { doesExist in
    if doesExist == true {
        print("yep, it exists")
    } else {
        print("Nope - it's not there")
    }
}

print("this code will execute before the above code")

那将打印是的,它存在

这是执行查询的实际函数。请注意我们如何使用完成处理程序,即在完成时@escaping 闭包。

//determine if a user name exists in Firestore, return true if it does, false if not
func doesUserNameExist(userName: String, completion: @escaping( (Bool) -> Void) ) {
    let usersCollection = self.db.collection("users")
    usersCollection.whereField("name", isEqualTo: userName).getDocuments(completion: { querySnapshot, error in
        if let err = error {
            print(err.localizedDescription)
            return
        }
        
        guard let docs = querySnapshot?.documents else { return }
        
        if docs.count > 0 {
            completion(true)
        } else {
            completion(false)
        }
    })
}

这是从异步函数“返回”数据的典型方式,因为它允许函数执行,数据有效,然后以异步方式将该数据传递回调用函数。

请注意,调用函数之后的任何代码,如下所示

print("this code will execute before the above code")

将在函数闭包中的代码之前执行。

编辑

上面的这个调用是这样调用的

self.doesUserNameExist(userName: "Jay", completion: { doesItExist in
    print(doesItExist)
})

推荐阅读