Swift - 如何使用Firebase中的“shouldChangeTextInRange”进行实时搜索? [英] Swift - How Can I use 'shouldChangeTextInRange' with Firebase for real time searching?
问题描述
我不知道如何使用 shouldChangeTextInRange 创建 Firebase matchesRegex查询和列出当前结果。
在Parse Cloud中,我已经在Parse中搜索用户名或用户全名。如果有人点亮了我在Firebase中的路线,那就太好了。
//搜索已更新
func searchBar(searchBar:UISearchBar,shouldChangeTextInRange range:NSRange,replacementText text:String) - > Bool {
//找到用户名
let usernameQuery = PFQuery(className:_User)
usernameQuery.whereKey(username,matchesRegex:(?i) + searchBar.text!)
usernameQuery.findObjectsInBackgroundWithBlock {(objects:[PFObject]?,error:NSError?) - >无效
如果错误== nil {
//如果根据用户名字段中输入的文本找不到对象,则用全名
查找对象! isEmpty {
let fullnameQuery = PFUser.query()
fullnameQuery?.whereKey(fullname,matchesRegex:(?i)+ self.searchBar.text!)
全名查询?.findObjectsInBackgroundWithBlock({(objects:[PFObject]?,error:NSError?) - >无效
如果错误== nil {
// clean up
self.usernameArray.removeAll(keepCapacity:false)
self.avaArray.removeAll(keepCapacity:false)
//找到相关对象
用于对象中的对象!{
self.usernameArray.append(object.objectForKey(username)as!String)
self.avaArray.app end(object.objectForKey(avatar)as! PFFile)
}
//重新加载$ b $ b self.tableView.reloadData()
}
})
$ b //清理
self.usernameArray.removeAll(keepCapacity:false)
self.avaArray。 removeAll(keepCapacity:false)
//找到相关对象
用于对象中的对象! {
self.usernameArray.append(object.objectForKey(username)as!String)
self.avaArray.append(object.objectForKey(avatar)as!PFFile)
}
//重新加载$ b $ b self.tableView.reloadData()
}
返回true
}
更新1:
我不能用相同的父名来做,snap.value没有给我回应,甚至没有编译。所以我试图做两个单独的父节点: Firebase截图链接
我在xcode控制台上为每个字母笔划 first_name子节点添加了 indexOn安全警告 :
[Firebase] 使用未指定的索引。考虑在/ people_spell中添加.indexOn:first_name / T以符合您的安全规则,以获得更好的性能
$ b[Firebase] 使用未指定指数。考虑在/ people_spell中添加.indexOn:first_name / Te到你的安全规则以获得更好的性能
...更多次数
我已经尝试了这些安全规则,但没有解决这些问题。它不包含每个子节点。如何提供这个?
people_spell:{
.read:auth!== null ,
.write:auth!== null,
.indexOn:first_name
},
people:{
.read:auth!== null,
.write:auth!== null,
.indexOn:first_name
}
我正在使用这些代码行:
let peopleSpellRef = Firebase(url:https://sampleproject.firebaseio.com/people_spell)
let peopleRef = Firebase(url:https ://sampleproject.firebaseio.com/people)
func searchBar(searchBar:UISearchBar,shouldChangeTextInRange range:NSRange,replacementText text:String) - > Bool {
self.usernameArray.removeAll(keepCapacity:false)
peopleSpellRef.queryOrderedByChild(first_name / \(searchBar.text!))。queryEqualToValue(true)
.observeEventType(.Value,withBlock:{snapshot in
let enumerator = snapshot.children
while let rest = enumerator.nextObject()as?FDataSnapshot {
peopleRef.childByAppendingPath(\(rest.key))。observeEventType(.Value,withBlock:{snapshot in
self.usernameArray.removeAll(keepCapacity:false)
let str:String =(snapshot.value.objectForKey(first_name))as!(String)
print(str)
self.usernameArray.append(str)
self.userkeyArray.append(snapshot.key)
self.tableView.reloadData()
})
}
self .usernameArray.removeAll(keepCapacity:false)
self。 tableView.reloadData()
))
return true
}
这不是Firebase的工作原理,您无法直接在Firebase中为子字符串进行实时搜索。但是,您可以设置要搜索的Firebase数据的格式,还有一些其他方法也可以实现目标。
其中一个很简单:从Firebase加载数据到数组和NSPredicate搜索(或其他方法)通过数组。
另一个是查询完整的字符串很容易;只要文本被分解成你想要搜索的块:
people
person_0
first_name:Ted
last_name:Stryker
位置:坐下并面向前方
person_1
first_name:Teddy
您可以搜索first_name中的'Ted'或last_name中的'Stryker',但不能在位置搜索'front'。 >
现在,解决方法并记住磁盘空间是便宜。
节点可以创建,可以让您搜索各种各样的东西
people
person_0
first_name //名字是从上面的Ted b $ b T:true
Te:true
Ted:true
ed:true
d:true
e:true
person_1
first_name / /名字是从
以上的Teddy T:true
Te:true
Ted:true
等
有了这个结构我们可以找到以Ted开头的所有名字
peopleRef.queryOrderedByChild(first_name / Ted)。queryEqualToValue(true)
.observeEventType(.Value,withBlock:{snapshot in
for snapshot.children {
print(child.value)
}
})
可以执行其他搜索;搜索所有包含e或Te等的名字。
如果这纯粹是您正在搜索在文本字段中执行自动填充的情况(例如)ping firebase的按键击键基础是行不通的。
从Firebase加载数据到数组或字典(或其他)可能是最好的解决方案。
I wonder that how creating Firebase matchesRegex query and listing current results using shouldChangeTextInRange.
I have did it before in Parse for searching username or user fullname in Parse Cloud. If someone shed light my path to do it in Firebase, it would be great.
// search updated func searchBar(searchBar: UISearchBar, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool { // find by username let usernameQuery = PFQuery(className: "_User") usernameQuery.whereKey("username", matchesRegex: "(?i)" + searchBar.text!) usernameQuery.findObjectsInBackgroundWithBlock { (objects:[PFObject]?, error:NSError?) -> Void in if error == nil { // if no objects are found according to entered text in username column, find by fullname if objects!.isEmpty { let fullnameQuery = PFUser.query() fullnameQuery?.whereKey("fullname", matchesRegex: "(?i)" + self.searchBar.text!) fullnameQuery?.findObjectsInBackgroundWithBlock({ (objects:[PFObject]?, error:NSError?) -> Void in if error == nil { // clean up self.usernameArray.removeAll(keepCapacity: false) self.avaArray.removeAll(keepCapacity: false) // found related objects for object in objects! { self.usernameArray.append(object.objectForKey("username") as! String) self.avaArray.append(object.objectForKey("avatar") as! PFFile) } // reload self.tableView.reloadData() } }) } } // clean up self.usernameArray.removeAll(keepCapacity: false) self.avaArray.removeAll(keepCapacity: false) // found related objects for object in objects! { self.usernameArray.append(object.objectForKey("username") as! String) self.avaArray.append(object.objectForKey("avatar") as! PFFile) } // reload self.tableView.reloadData() } return true }
Update 1:
I couldn't do it using same parent name, snap.value didn't give me response, even not compile. So I have tried to do two separate parent node like that: firebase screen shot link
I'm getting indexOn security warning for each letter stroke first_name subnodes on xcode console:
[Firebase] Using an unspecified index. Consider adding ".indexOn": "first_name/T" at /people_spell to your security rules for better performance
[Firebase] Using an unspecified index. Consider adding ".indexOn": "first_name/Te" at /people_spell to your security rules for better performance
... much more times
I have tried these security rules it didn't solve these problems. It doesn't encompass each subnodes. How Can I provide this?
"people_spell": { ".read": "auth !== null", ".write": "auth !== null", ".indexOn": "first_name" }, "people": { ".read": "auth !== null", ".write": "auth !== null", ".indexOn": "first_name" }
I'm using these lines of codes:
let peopleSpellRef = Firebase(url: "https://sampleproject.firebaseio.com/people_spell") let peopleRef = Firebase(url: "https://sampleproject.firebaseio.com/people") func searchBar(searchBar: UISearchBar, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool { self.usernameArray.removeAll(keepCapacity: false) peopleSpellRef.queryOrderedByChild("first_name/\(searchBar.text!)").queryEqualToValue(true) .observeEventType(.Value, withBlock: { snapshot in let enumerator = snapshot.children while let rest = enumerator.nextObject() as? FDataSnapshot { peopleRef.childByAppendingPath("\(rest.key)").observeEventType(.Value, withBlock: { snapshot in self.usernameArray.removeAll(keepCapacity: false) let str: String = (snapshot.value.objectForKey("first_name")) as! (String) print(str) self.usernameArray.append(str) self.userkeyArray.append(snapshot.key) self.tableView.reloadData() }) } self.usernameArray.removeAll(keepCapacity: false) self.tableView.reloadData() }) return true }
解决方案This is not how Firebase works and you can't directly do a 'real time search' in Firebase for a substring. But, you can format your Firebase data to be searched and there are a couple of other methods which will also accomplish the goal.
One is straightforward: load your data from Firebase into an array and NSPredicate search (or other methods) through the array.
Another is that query'ing for full strings is easy; as long as the text is broken up into the chunks you want to search for:
people person_0 first_name: "Ted" last_name: "Stryker" position: "sitting down and facing front" person_1 first_name: "Teddy"
You can search for 'Ted' in first_name or 'Stryker' in last_name but you cannot search for 'front' in position.
Now the workaround and keep in mind disk space is cheap.
A node can be created that will let you search for stuff in a variety of ways
people person_0 first_name //First name is Ted from above T: true Te: true Ted: true ed: true d: true e: true person_1 first_name //First name is Teddy from above T: true Te: true Ted: true etc
With this structure we can find all first names that start with Ted
peopleRef.queryOrderedByChild("first_name/Ted").queryEqualToValue(true) .observeEventType(.Value, withBlock: { snapshot in for child in snapshot.children { print(child.value) } })
Other searches can be performed; searching for all first names that contain e or Te etc.
If this is purely a situation where you are searching to perform an autofill in a text field (for example) pinging firebase on a keystroke by keystroke basis isn't going to work well.
Loading the data from Firebase into an array, or dictionary (or whatever) will probably be your best solution.
这篇关于Swift - 如何使用Firebase中的“shouldChangeTextInRange”进行实时搜索?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!