I search for users while typing. However at the end it returns every users. I don't know why exactly this happens. It seems alright
class func findUsers(text: String)->[User]{
let user = User()
var users = [User]()
ref.child("Users").queryOrderedByChild("name").queryStartingAtValue(text).observeEventType(.Value, withBlock: { snapshot in
for u in snapshot.children{
user.name = u.value!["name"] as? String
user.surname = u.value!["surname"] as? String
user.email = u.value!["email"] as? String
user.score = u.value!["score"] as? Int
user.status = u.value!["status"] as? Int
user.id = u.value!["id"] as? String
user.pin = u.value!["pin"] as? String
users.append(user)
print(user.name)
}
})
print("users:", users)
return users
}
Use Swift Package Manager to install and manage Firebase dependencies. Visit our installation guide to learn about the different ways you can add Firebase SDKs to your Apple project, including importing frameworks directly and using CocoaPods. In Xcode, with your app project open, navigate to File > Add Packages.
The character \uf8ff used in the query is a very high code point in the Unicode range (it is a Private Usage Area [PUA] code). Because it is after most regular characters in Unicode, the query matches all values that start with queryText .
You are using queryStartingAtValue
. From the documentation:
The
FIRDatabaseQuery
instance returned byqueryStartingAtValue:childKey
will respond to events at nodes with a value greater than startValue, or equal to startValue and with a key greater than or equal to childKey.
So keep in mind that if you search for the name
of an user it will give all the users that have name greater in alphabetic order than the given one. You need to set a queryEndingAtValue
to limit the query range.
ref.child("Users").queryOrderedByChild("name").queryStartingAtValue(text).queryEndingAtValue(text+"\u{f8ff}")
Firebase legacy documentation is such a good resource to understand on how firebase handle queries. There you will find:
The f8ff character used in the query above is a very high code point in the Unicode range. Because it is after most regular characters in Unicode, the query matches all values that start with a b.
You might also get interested in Elasticsearch. Flashlight is a node service that integrates elasticsearch and firebase.
As pointed out in the comments this won't work if the string you are searching for has upper case characters. The solution in this case is to have an additional field in the object with the info you are searching all in lower case. So if you have Satoshi Nakamoto
as name
you would save an additional nameSearch
property with satoshi nakamoto
.
And finally make sure your searching string is in lower case too.
There is a few other problems with your code.
You are setting an observer. It will trigger the callback anytime your data changes so you should be resetting the users
array inside the callback so you don't have duplicated and dirty data.
Your function won't return the users with the data since firebase call is async. When you call return users
you won't have the users array populated. I recommend you using self.users = users
instead of returning it in the function. Otherwise, if you want to proceed with the current approach and return it, you should set a completion handler.
class func findUsers(text: String)->Void{
ref.child("Users").queryOrderedByChild("name").queryStartingAtValue(text).queryEndingAtValue(text+"\u{f8ff}").observeEventType(.Value, withBlock: { snapshot in
var user = User()
var users = [User]()
for u in snapshot.children{
user.name = u.value!["name"] as? String
...
users.append(user)
}
self.users = users
})
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With