Mathias Erligmann
Mathias Erligmann

Reputation: 25

Retrieving data from a query in swift with Firebase

I have this database structure :

Users
   userid1
      username : username1
      otherdata : otherdata1

   userid2
      username : username2
      otherdate : otherdata2

What I'm looking for is to display the usernames of my user in a tableview when one user use a uisearchbar on top of the table view. Here's what I have so far :

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    ref = Database.database().reference()
    let strSearch = searchBar.text
    ref.child("Users").queryOrdered(byChild: "username").queryStarting(atValue: strSearch).queryEnding(atValue: strSearch! + "\u{f8ff}").observeSingleEvent(of: .value, with: { (snapshot) in
        var fetchedList = snapshot.value as! [AnyObject]
        for obj in fetchedList { 
        print(obj["username"] as? String)
   }

    }) { (err) in
        print(err)
    }
}

But I'm stuck because this doesn't display the usernames, my app keeps crashing, before I run I get this warning : "expression implicitly coerced from 'String?' to Any" and when I fix it with Xcode like this :

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    ref = Database.database().reference()
    let strSearch = searchBar.text
    ref.child("Users").queryOrdered(byChild: "username").queryStarting(atValue: strSearch).queryEnding(atValue: strSearch! + "\u{f8ff}").observeSingleEvent(of: .value, with: { (snapshot) in
        let fetchedList = snapshot.value as! [AnyObject]
        for obj in fetchedList {
            print(obj["username"] as Any)
        }

    }) { (err) in
        print(err)
    }
}

It's not working aswell my app crash as before. Can someone tell me what I'm doing wrong.

Upvotes: 1

Views: 441

Answers (1)

Jen Person
Jen Person

Reputation: 7546

When I ran your code, I got the following error:

Could not cast value of type 'NSNull' (0x11202a570) to 'NSArray' (0x112029d78).

So I have a couple of suggestions:

  1. The snapshot might be null, so make sure you handle this with and if let or a guard statement.

  2. Use snapshot.children.allObjects to iterate, not snapshot.Value, which cannot be cast to an array.

Also, as a side note, you can pass the searchText parameter into your query rather than using searchBar.text.

The result would be something like this:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    ref = Database.database().reference()
    ref.child("Users").queryOrdered(byChild: "username").queryStarting(atValue: searchText).queryEnding(atValue: searchText + "\u{f8ff}").observeSingleEvent(of: .value, with: { (snapshot) in
        // cast to an array of DataSnapshots
        guard let fetchedList = snapshot.children.allObjects as? [DataSnapshot] else { return }
        // iterate through array, cast value to dictionary
        for obj in fetchedList {
            let objDict = obj.value as! [String: AnyObject]
            print(objDict["username"])
        }
    }) { (err) in
        print(err)
    }
}

Upvotes: 1

Related Questions