简体   繁体   English

努力通过 Firestore 传递单个文档 - Swift

[英]Struggling to pass a single document through Firestore - Swift

Here is my customer class:这是我的客户 class:

class Customer {
    // Creating a customer
    let name: String
    let surname: String
    let contactNo: String
    let email: String
   
    init(name: String,surname: String,contactNo: String,email: String) {
        
        self.name = name
        self.surname = surname
        self.contactNo = contactNo
        self.email = email
    }
}

This is the code I'm using which keeps returning a nil:这是我正在使用的代码,它不断返回零:

class ProfileCus: UIViewController {
    // Labels to display data
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var surnameLabel: UILabel!
    @IBOutlet weak var emailLabel: UILabel!
    @IBOutlet weak var contactLabel: UILabel!
    
    // Reference to customer collection in Firestore
    private var  customerRefCollection = Firestore.firestore().collection("customers")
    
    // Customer Object
    private var customer =  Customer(name: "a",surname: "a",contactNo: "a",email: "a")
    
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
         getDataFromFirebase{
               self.customerRefCollection = Firestore.firestore().collection("customers")
                
               print(self.customer,"debug step 5")
               self.nameLabel.text = self.customer.name
               self.surnameLabel.text = self.customer.surname
               self.emailLabel.text = self.customer.email
               self.contactLabel.text = self.customer.contactNo
           }
    }
    
    func getDataFromFirebase(completion:@escaping() -> ()){
                    print(self.customer,"debug step 1")
                    let userID = Auth.auth().currentUser?.uid
                    print(userID,"debug step 2")
                // Locate the user information on Firestore
                    customerRefCollection.document(userID!).getDocument { (snapshot, error) in
                    if let err = error {
                        debugPrint("Error fetching documents: \(err)")
                    }
                    else {
                        // Ensure that if there's nothing in the document that the function returns
                    guard let snap = snapshot else {return}
                    print(snap, "debug step 3")
                    // Parse the data to the customer model
                    let data = snap.data()
                    
                    let name = data?["name"] as? String ?? ""
                    let surname = data?["surname"] as?  String ?? ""
                    let email = data?["email"] as? String ?? ""
                    let contact = data?["contact no"] as? String ?? ""
                    // Create the customer and pass it to the global variable
                    let cus = Customer(name: name, surname: surname, contactNo: contact, email: email)
                    print(self.customer,"debug step 4")
                    self.customer = cus
                }
                    completion()
            }
    }
}

Can anyone please help me understand what I am doing wrong because the snapshot does return but the way I parse the data is wrong because the customer object returns a nil.谁能帮我理解我做错了什么,因为快照确实返回,但我解析数据的方式是错误的,因为客户 object 返回零。

I have added print statements with tags saying debug step 1 ect so you can follow what happens at run time, here is the output:我添加了带有标签的打印语句,说明调试步骤 1 等,因此您可以跟踪运行时发生的情况,这里是 output:

020-08-13 21:15:20.388052+0200 Clean Wheels[8599:430648] 6.29.0 - [Firebase/Analytics][I-ACS023012] Analytics collection enabled Customer(name: "a", surname: "a", contactNo: "a", email: "a") debug step 1 Optional("RWVTDIUuL1eahOLpZT1UmMl0cja2") debug step 2 <FIRDocumentSnapshot: 0x6000017499f0> debug step 3 Customer(name: "a", surname: "a", contactNo: "a", email: "a") debug step 4 Customer(name: "", surname: "", contactNo: "", email: "") debug step 5 020-08-13 21:15:20.388052+0200 Clean Wheels[8599:430648] 6.29.0 - [Firebase/Analytics][I-ACS023012] 启用分析收集客户(姓名:“a”,姓:“a”, contactNo: "a", email: "a") 调试步骤 1 可选("RWVTDIUuL1eahOLpZT1UmMl0cja2") 调试步骤 2 <FIRDocumentSnapshot: 0x6000017499f0> 调试步骤 3 客户(姓名:“a”,姓:“a”,联系人编号: ", email: "a") 调试步骤 4 客户(姓名: "", 姓: "", contactNo: "", email: "") 调试步骤 5

It seems to me as if the data function is not the correct function to use because when I hard code the values its shows up in the UI Profile View, is there perhaps an alternative?在我看来,好像数据 function 不是正确的 function 使用,因为当我硬编码它显示在 UI 配置文件视图中的值时,是否有替代方法?

Output once the code runs代码运行后 Output

There are a number of ways you can do this but what I'd suggest is passing the customer object through the completion handler (to the caller).有很多方法可以做到这一点,但我建议将客户 object 通过完成处理程序(给调用者)。 You could also configure the customer object to take the document snapshot in its initializer (instead of taking 4 separate properties) and either return a customer object or nil (this would require a failable intializer which is incredibly basic).您还可以配置客户 object 以在其初始化程序中获取文档快照(而不是获取 4 个单独的属性)并返回客户 object 或nil (这将需要一个非常基础的可失败初始化程序)。 Also, I didn't see a need to declare so many instance properties (in this example, anyway) so I took them out.另外,我认为不需要声明这么多实例属性(无论如何,在这个例子中),所以我把它们取出来了。 I also made the customer number an integer, not a string (to illustrate how I would structure the data).我还将客户编号设为 integer,而不是字符串(以说明我将如何构建数据)。

class Customer {
    let name: String
    let surname: String
    let contactNo: Int // change this back to a string
    let email: String
   
    init(name: String, surname: String, contactNo: Int, email: String) {
        self.name = name
        self.surname = surname
        self.contactNo = contactNo
        self.email = email
    }
}

class ProfileCus: UIViewController {
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var surnameLabel: UILabel!
    @IBOutlet weak var emailLabel: UILabel!
    @IBOutlet weak var contactLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        getCustomer { (customer) in
            if let customer = customer {
                print(customer)
            } else {
                print("customer not found")
            }
        }
    }
    
    private func getCustomer(completion: @escaping (_ customer: Customer?) -> Void) {
        guard let userID = Auth.auth().currentUser?.uid else {
            completion(nil)
            return
        }
        Firestore.firestore().collection("customers").document(userID).getDocument { (snapshot, error) in
            if let doc = snapshot,
                let name = doc.get("name") as? String,
                let surname = doc.get("surname") as? String,
                let contact = doc.get("contact") as? Int, // cast this as a string
                let email = doc.get("email") as? String {
                let customer = Customer(name: name, surname: surname, contactNo: contact, email: email)
                completion(customer)
            } else {
                if let error = error {
                    print(error)
                }
                completion(nil)
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM