Aryan Sharma
Aryan Sharma

Reputation: 635

Swift 3: FirebaseDB returning nil when child is present

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.

Upvotes: 0

Views: 200

Answers (2)

Frank van Puffelen
Frank van Puffelen

Reputation: 598740

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 {

Upvotes: 0

TheBen
TheBen

Reputation: 3522

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.

Upvotes: 1

Related Questions