0
votes

I have linked Firebase to my app. When I'm trying to read data from the DB, data is present in the snapshot. But when a child is read, it returns nil.

Here's the code:

    func checkForDuplicateScan(qrCode: String) {

    DataService.ds.REF_SAMPLES.observeSingleEvent(of: .value, with: { (snapshot) in

        if let dict = snapshot.value as? [String:Any] {
            print(dict)
            print(qrCode)
            print(dict["\(qrCode)"])
            if let sampleDict = dict[qrCode] as? [String:Any] {
                print(sampleDict)
                if let isScanned = sampleDict["scanned"] as? Bool {
                    if isScanned == true {
                        print("Already Scanned")
                        let alert = UIAlertController(title: "Already Redeemed", message: "This offer has already been redeemed by you. Stay tuned.", preferredStyle: UIAlertControllerStyle.alert)
                        alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: { (alert) in
                            self.tabBarController?.selectedIndex = 0
                        }))
                        self.present(alert, animated: true, completion: nil)
                    } else {
                        print("New Scan")
                        self.updateQRCode(qrCode: qrCode)
                    }
                } else {
                    print("Error: can't read/find 'scanned' ")
                }
            }else {
                print("Error: Invalid Code Scanned")
                let alert = UIAlertController(title: "Invalid QR Code Scanned", message: "The code that you've scanned is Invalid.", preferredStyle: UIAlertControllerStyle.alert)
                alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (alert) in
                    self.tabBarController?.selectedIndex = 0
                }))
                self.present(alert, animated: true, completion: nil)
            }
        } else {
            print("Error: can't get dictionary from snapshot value")
        }
    })
}

Here's the console log:

Console log

The log:

  1. The dictionary came from printing dict.
    print(dict)

  2. The 'test13' came from
    print(qrCode)

  3. The 'nil' came from
    print(dict["\(qrCode)"])

This code was working as of yesterday but has failed today.

Help me out!!

Edit: This is the data that I'm trying to read.

enter image description here

Here's the JSON file as well JSON FILE

Update: Looks like I've found out the problem here.

When I run this code, nothing is printed.

if let newDict = dict[qrCode] as? NSDictionary {
     print(newDict)
}

But, when I do this, the dict is accessible.

if let newDict = dict["test10"] as? NSDictionary {
     print(newDict)
}

Note that qrCode is a string having value "test10"

Wierd asf!! Still can't figure the reason behind it and how to rectify this.

2
I have no idea which line(s) in the log come from what code.Frank van Puffelen
@FrankvanPuffelen updatedAryan Sharma
You've included a picture of the JSON tree in your question. Please replace that with the actual JSON as text, which you can easily get by clicking the Export JSON link in your Firebase Database console. Having the JSON as text makes it searchable, allows us to easily use it to test with your actual data and use it in our answer and in general is just a Good Thing to do.Frank van Puffelen

2 Answers

1
votes

Just something to check, your problem seems to be with data type and not with Firebase data. Hence, you are getting the "Error: Invalid Code Scanned". I always go with something like:

if let value = snapshot.value as? NSDictionary {
    let username = value?["username"] as? String ?? ""
    etc ...
}

[String:Any] has caused problems for me in the past. Anyhow, it would be helpful to provide a sample of your data which you're trying to read.

0
votes

While the code should print, it looks like a bad approach anyway. You're downloading all QR codes from the database to the client, to then check if one of them exists. The more data is in the database, the more data you'll download for each check. It's much more efficient to attach the observer one level lower in the database:

func checkForDuplicateScan(qrCode: String) {
  DataService.ds.REF_SAMPLES.child(qrCode).observeSingleEvent(of: .value, with: { (snapshot) in
    if snapshot.exists() {
        if let sampleDict = snapshot.value as? [String:Any] {
            if let isScanned = sampleDict["scanned"] as? Bool {
                if isScanned == true {