Lukas Bimba
Lukas Bimba

Reputation: 826

Swift Firebase QueryOrdered

I have a registration page for a business location and am comparing if the Latitude and Longitudes match with any existing childs in the database. This code sometimes works and then stops working. When it stops working I would be pressing on the "Create Account Action" and nothing would happen. I added a print("Sign Up Button Tapped Firebase Problem") so I know that the button is actually firing. Why does this code sometimes work and sometimes not? Whats the solution to my problem? Thanks.

@IBAction func createAccountAction(_ sender: Any) {
    let email = self.emailTextField.text!
    let password = self.passwordTextField.text!

    if firstName.text == "" {
        CommonUtils.sharedUtils.showAlert(self, title: "Error", message: "Please Enter Your First Name.")
    }
    if lastName.text == "" {
        CommonUtils.sharedUtils.showAlert(self, title: "Error", message: "Please Enter Your Last Name.")
    }
    if companyPosition.text == "" {
        CommonUtils.sharedUtils.showAlert(self, title: "Error", message: "Please Enter Your Company Position.")
    }
    if businessName.text == "" {
        CommonUtils.sharedUtils.showAlert(self, title: "Error", message: "Please Enter The Business Name.")
    }
    if businessStreet.text == "" {
        CommonUtils.sharedUtils.showAlert(self, title: "Error", message: "Please Enter The Business's Street.")
    }
    if businessCity.text == "" {
        CommonUtils.sharedUtils.showAlert(self, title: "Error", message: "Please Enter The City.")
    }
    if businessState.text == "" {
        CommonUtils.sharedUtils.showAlert(self, title: "Error", message: "Please Enter The State.")
    }
    if businessZIP.text == "" {
        CommonUtils.sharedUtils.showAlert(self, title: "Error", message: "Please Enter The ZIP.")
    }
    if businessPhone.text == "" {
        CommonUtils.sharedUtils.showAlert(self, title: "Error", message: "Please Enter The Business's Phone.")
    }
    if businessWebsite.text == "" {
        CommonUtils.sharedUtils.showAlert(self, title: "Error", message: "Please Enter The Business Website.")
    }
    if businessLatitude.text == "" {
        CommonUtils.sharedUtils.showAlert(self, title: "Error", message: "Please Enter The Business Latitude.")
    }
    if businessLongitude.text == "" {
        CommonUtils.sharedUtils.showAlert(self, title: "Error", message: "Please Enter The Business Longitude.")
    }

    print("Sign Up Button Tapped Firebase problem")

    self.ref.child("Businesses").queryOrdered(byChild: "businessLatitude").queryEqual(toValue: self.businessLatitude.text!).observeSingleEvent(of: .value, with: { snapshot in
        if (snapshot.value! is NSNull) {
            print("Not Found - GOOD")
            if email != "" && password != "" && self.firstName.text != "" && self.lastName.text != "" && self.companyPosition.text != "" && self.businessName.text != "" && self.businessStreet.text != "" && self.businessCity.text != "" && self.businessState.text != "" && self.businessZIP.text! != "" && self.businessPhone.text != "" && self.businessWebsite.text != "" && self.businessLatitude.text != "" && self.businessLongitude.text != "" {
                // search for businessLatitude
                CommonUtils.sharedUtils.showProgress(self.view, label: "Registering...")
                FIRAuth.auth()?.createUser(withEmail: email, password: password, completion:  { (user, error) in
                    if error == nil {
                        FIREmailPasswordAuthProvider.credential(withEmail: email, password: password)
                        self.ref.child("Businesses").child(user!.uid).setValue(["firstName":self.firstName.text!,"lastName":self.lastName.text!, "companyPosition":self.companyPosition.text!,"businessName":self.businessName.text!, "businessStreet":self.businessStreet.text!, "businessCity":self.businessCity.text!, "businessState":self.businessState.text!, "businessZIP":self.businessZIP.text!, "businessPhone":self.businessPhone.text!, "businessWebsite":self.businessWebsite.text!,"businessLatitude":self.businessLatitude.text!, "businessLongitude":self.businessLongitude.text!, "approvalStatus":self.isApproved, "email":email ])
                        CommonUtils.sharedUtils.hideProgress()
                        let photoViewController = self.storyboard?.instantiateViewController(withIdentifier: "BusinessProfile")
                        self.navigationController?.pushViewController(photoViewController!, animated: true)
                    } else {
                        DispatchQueue.main.async(execute: {() -> Void in
                            CommonUtils.sharedUtils.hideProgress()
                            CommonUtils.sharedUtils.showAlert(self, title: "Error", message: (error?.localizedDescription)!)
                        })
                    }
                })
            } else {
                let alert = UIAlertController(title: "Error", message: "Enter email & password!", preferredStyle: .alert)
                let action = UIAlertAction(title: "OK", style: .default, handler: nil)
                alert.addAction(action)
            }
            } else {
            print(snapshot.value!)
            if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {
                for snap in snapshots {
                    let thisLongitude = snap.childSnapshot(forPath: "businessLongitude").value as! String
                    if thisLongitude == self.businessLongitude.text! {
                        // handle repeated location
                        if snap.exists() == true {
                            DispatchQueue.main.async(execute: {() -> Void in
                                CommonUtils.sharedUtils.hideProgress()
                                CommonUtils.sharedUtils.showAlert(self, title: "Error", message: "This Place Already Is Registered")
                            })
                        }
                    }
                }
            }
        }
    })
}

More Info

If I set this code like this (Code below) and run it, it works yet it does the check if the same "businessLatitude" exists AFTER the user registers and the user is saved into the database. THEN, when I set it back to the code above the above code runs and does the check without registering the user into the database (Exactly what I want). Why does it run after I do the flip-flop? lol

if email != "" && password != "" && self.firstName.text != "" && self.lastName.text != "" && self.companyPosition.text != "" && self.businessName.text != "" && self.businessStreet.text != "" && self.businessCity.text != "" && self.businessState.text != "" && self.businessZIP.text! != "" && self.businessPhone.text != "" && self.businessWebsite.text != "" && self.businessLatitude.text != "" && self.businessLongitude.text != "" {
        // search for businessLatitude
        CommonUtils.sharedUtils.showProgress(self.view, label: "Registering...")
        FIRAuth.auth()?.createUser(withEmail: email, password: password, completion:  { (user, error) in
            if error == nil {
                FIREmailPasswordAuthProvider.credential(withEmail: email, password: password)
                self.ref.child("Businesses").child(user!.uid).setValue(["firstName":self.firstName.text!,"lastName":self.lastName.text!, "companyPosition":self.companyPosition.text!,"businessName":self.businessName.text!, "businessStreet":self.businessStreet.text!, "businessCity":self.businessCity.text!, "businessState":self.businessState.text!, "businessZIP":self.businessZIP.text!, "businessPhone":self.businessPhone.text!, "businessWebsite":self.businessWebsite.text!,"businessLatitude":self.businessLatitude.text!, "businessLongitude":self.businessLongitude.text!, "approvalStatus":self.isApproved, "email":email ])
                CommonUtils.sharedUtils.hideProgress()
                let photoViewController = self.storyboard?.instantiateViewController(withIdentifier: "BusinessProfile")
                self.navigationController?.pushViewController(photoViewController!, animated: true)
            } else {
                DispatchQueue.main.async(execute: {() -> Void in
                    CommonUtils.sharedUtils.hideProgress()
                    CommonUtils.sharedUtils.showAlert(self, title: "Error", message: (error?.localizedDescription)!)
                })
            }
        })
    } else {
        let alert = UIAlertController(title: "Error", message: "Enter email & password!", preferredStyle: .alert)
        let action = UIAlertAction(title: "OK", style: .default, handler: nil)
        alert.addAction(action)
    }

    self.ref.child("Businesses").queryOrdered(byChild: "businessLatitude").queryEqual(toValue: self.businessLatitude.text!).observeSingleEvent(of: .value, with: { snapshot in
        if (snapshot.value! is NSNull) {
            print("Not Found - GOOD")
            } else {
            print(snapshot.value!)
            if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {
                for snap in snapshots {
                    let thisLongitude = snap.childSnapshot(forPath: "businessLongitude").value as! String
                    if thisLongitude == self.businessLongitude.text! {
                        // handle repeated location
                        if snap.exists() == true {
                            DispatchQueue.main.async(execute: {() -> Void in
                                CommonUtils.sharedUtils.hideProgress()
                                CommonUtils.sharedUtils.showAlert(self, title: "Error", message: "This Place Already Is Registered")
                            })
                        }
                    }
                }
            }
        }
    })
}

Even More Info

I just changed my "Read" + "Write" rules in Firebase to "True". I've been reading how this is a security risk? This is working so far, yet I am testing to see if it will stop working like it has before. I will keep this updated....

{
"rules": {
".read": "true",
".write": "true",
"Businesses": {
  "$Businesses_id" : {
    ".indexOn": "businessLatitude"
  }
}
}
}

Picture of compiler when setting break point

This is the compiler when the code won't work and I set a breakpoint at the top line

This is what the compiler looks like after I do the "Hack" to make it work. What is different is "Provider Data/API Key/ User Id"

Upvotes: 2

Views: 1236

Answers (1)

Jay
Jay

Reputation: 35657

I'm not sure there's enough info in the question to actually answer specifically but eliminating some variables may lead to a solution. So let's try to generate an answer by simplifying...

What I did was create a node in Firebase for testing like this:

app_name
   Businesses
     bus_0
       businessLatitude: "thing"
     bus_1
       businessLatitude: "test"
     bus_2
       businessLatitude: "stuff"

I then created a brand new Firebase project and pasted the following code into the viewDidLoad function. This code is copy and pasted from your question, eliminating most of the 'stuff' in the closure.

//self.ref is a ref to my firebase.

override func viewDidLoad() {

     self.ref.child("Businesses").queryOrdered(byChild: "businessLatitude")
                                 .queryEqual(toValue: "test")
                                 .observeSingleEvent(of: .value, with: { snapshot in
         if (snapshot.value! is NSNull) {
             print("nothing found")
         } else {
             print("found it!")
             print(snapshot)
         }
     })
}

and then built and ran the app. The output was:

found it!
Snap (Businesses) {
    "bus_1" =     {
        businessLatitude = test;
    };
}

Based on this result, the code in itself works correctly so there must be something else influencing the process. Perhaps another method is getting called or perhaps there's an asynchronous code issue.

I would suggest doing the same thing - create a new project and use the code posted above in it, and see if it works. If so, I would then comment out a lot of the code in your project and try to run it as bare-bones as possible, attempting to reduce the number of variables. Then get it working and add that code back in a bit at a time until it stops working.

Upvotes: 1

Related Questions