简体   繁体   English

停止查询Firebase?

[英]Stopping a query to firebase?

func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {

    if searchBar.text == nil || searchBar.text == "" {

        inSearchMode = false

    } else {

        if allInterestsArray.contains(searchBar.text!.lowercaseString) {

          ref.child(searchBar.text!.lowercaseString).child("users")

            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in

                print("this should be running")
                print(searchBar.text!.lowercaseString)

                let handle = roomsRef.observeSingleEventOfType(.Value, withBlock: { (snapshot: FIRDataSnapshot) in

                    print(snapshot.value)

                    if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {
                        for snap in snapshots {

                            print(snap)
                        }

                    }

                })
            }
        }
        else {
            print("doesn't exist")
        }


    }
}

I'm running a query to my firebase database when my searchBar.text is equal to something in my allInterestsArray. 当searchBar.text等于allInterestsArray中的值时,我正在对Firebase数据库运行查询。 This is being checked for on keystroke, and I'm using dispatch_after to prevent a query being sent until the user is probably done typing. 这是在击键时检查的,我正在使用dispatch_after来阻止发送查询,直到用户可能已经完成键入为止。

What is happening is if I have the item in my array of "Dog" and the user gets to "dog" and then types in an "s" which makes it "dogs"..the query is still being sent off for dog and then again for dogs, so I need to cancel the query up at the top of my textDidChange func I think so on each keystroke it's being canceled, and only after a second of no typing is the query being sent off. 发生的情况是,如果我在“ Dog”数组中有该项目,并且用户进入“ dog”,然后键入“ s”,使其变为“ dogs”。查询仍然针对dog和然后是狗,因此我需要在textDidChange函数的顶部取消查询,我认为在每次击键时都将其取消,并且仅在经过一秒钟的无输入后才发送该查询。

I was thinking of using removeHandle but I don't think that's what that's meant to be used for? 我当时在考虑使用removeHandle,但我不认为这是用来做什么的?

Example: 例:

If my array = ["dog","dogs","doggies"] 如果我的数组= [“ dog”,“ dogs”,“ doggies”]

The user types quickly enough so there's not a full 1 second between any two letters (one second because of the dispatch_after time I set) and they type in "dogs".. the query for dog should not have gone off, only for "dogs". 用户输入的速度足够快,因此任何两个字母之间都不会有完整的1秒钟(由于我设置的dispatch_after时间,所以没有1秒钟),他们输入了“ dogs”。。对dog的查询不应只对“ dogs”有效”。

This problem could be solved using a global variable called "keepSearching" as below : 可以使用一个名为“ keepSearching”的全局变量来解决此问题,如下所示:

EDIT : I've now also used NSTimer to give a one-second gap for "keepSearching" to be false. 编辑:我现在也使用NSTimer为“ keepSearching”提供一秒钟的间隔为假。

var keepSearching: Bool = true
var timer = NSTimer()
func timerAction() {
    keepSearching = false
}
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {

if searchBar.text == nil || searchBar.text == "" {
    inSearchMode = false

} 
else if(keepSearching) {

    if allInterestsArray.contains(searchBar.text!.lowercaseString) {


      // just in case user keeps on typing, invalidate the previous timer, before it happens.
      timer.invalidate()

      // schedule a new timer everytime.
      timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(timerAction), userInfo: nil, repeats: false)

      ref.child(searchBar.text!.lowercaseString).child("users")

        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in

            print("this should be running")
            print(searchBar.text!.lowercaseString)

            let handle = roomsRef.observeSingleEventOfType(.Value, withBlock: { (snapshot: FIRDataSnapshot) in

                print(snapshot.value)

                if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {
                    for snap in snapshots {

                        print(snap)
                    }

                }

            })
        }
    }
    else {
        print("doesn't exist")
    }
}

You could add a property that gets incremented every time a dispatch_after block is submitted, and check if that value corresponds to the current one. 您可以添加一个属性,该属性在每次提交dispatch_after块时都会增加,并检查该值是否对应于当前值。 This way you'll be able to tell if you should kick-off or not the request. 这样,您就可以确定是否应该启动请求。 Here how your controller class might look like (included only the relevant pieces to this question): 这是您的控制器类的外观(仅包括该问题的相关部分):

class MyController: <base class, protocols> {

    var requestsCounter = 0

    func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
        // mark that a new request is made
        self.requestsCounter++

        // save the number in a local var to be used when the block
        // actually executes
        let currentCounter = self.requestsCounter

        if searchBar.text == nil || searchBar.text == "" {
            inSearchMode = false
        } else {
            dispatch_after(...) { () -> Void in

            // if another dispatch_after was submitted, then the value of the 
            // currentCounter local variable won't match the property value,
            // so we should no longer proceeed
            guard currentCounter == self.requestsCounter  else { return }

            // ... the original code here
        }
    }

How does it work: 它是如何工作的:

  • the first time the delegate method is called, it increments the requestsCounter property, so now it has a value of 1 第一次调用委托方法时,它会增加requestsCounter属性,因此现在它的值为1
  • this value (1) gets saved into the local variable currentCounter , whos value is captured by the dispatch_after closure. 此值(1)保存到局部变量currentCounter ,其值由dispatch_after闭包捕获。
  • if the delegate method is called before dispatch_after executes the closure, then the requestsCounter will be incremented to 2, and a new currentCounter variable, with that value, will be created and captured by the 2nd dispatch_after closure 如果在dispatch_after执行闭包之前调用了委托方法,则requestsCounter将增加为2,并且将使用第二个dispatch_after闭包创建并捕获具有该值的新currentCounter变量。
  • now when the first dispatch_after closure executes, it captured currentCounter value will hold 1, but self.requestsCounter will be 2, thus the closure will return without doing actual work 现在,当执行第一个dispatch_after闭包时,它捕获的currentCounter值将保持为1,但是self.requestsCounter将为2,因此闭包将返回而不进行实际工作
  • the same logic applies for subsequent requests, the searchBar: textDidChange: delegate method will increment every time the requestsCounter property, which in turn will invalidate previously scheduled closures, as each captures the old values of the requestsCounter property. 同样的逻辑也适用于后续请求中, searchBar: textDidChange:委托方法将增加每次requestsCounter财产,这反过来会作废以前计划的封锁,因为每个捕捉的旧值requestsCounter财产。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM