在Swift 3中实时搜索节流

时间:2017-02-24 17:02:47

标签: ios swift swift3 uisearchbar alamofire

我尝试使用Swift在我的PHP API上进行搜索。到目前为止,我已经完成了这件事。

 var filteredData = [Products]()


 func getSearch(completed: @escaping DownloadComplete, searchString: String) {

        let parameters: Parameters = [
            "action" : "search",
            "subaction" : "get",
            "product_name"  : searchString,
            "limit" : "0,30"
        ]
        Alamofire.request(baseurl, method: .get, parameters: parameters).responseJSON { (responseData) -> Void in
            if((responseData.result.value) != nil) {
                let result = responseData.result

                if let dict = result.value as? Dictionary<String, AnyObject>{
                    if let list = dict["products_in_category"] as? [Dictionary<String, AnyObject>] {
                        if self.filteredData.isEmpty == false {
                            self.filteredData.removeAll()
                        }
                        for obj in list {
                            let manPerfumes = Products(productDict: obj)
                            self.filteredData.append(manPerfumes)
                        }
                    }
                }
                completed()
            }
        }
    }


extension SearchViewController: UISearchResultsUpdating {

    func updateSearchResults(for searchController: UISearchController) {

        if (searchController.searchBar.text?.characters.count)! >= 3 {
                    self.getSearch(completed: {
                    self.searchResultTable.reloadData()

                    self.searchResultTable.setContentOffset(CGPoint.zero, animated: true)
                }, searchString: searchController.searchBar.text!)


        } else {
            self.searchResultTable.reloadData()
        }


    }
}

表格视图正在使用filteredData进行更新。 我如何限制搜索,所以让我们说当用户写

"example" -> shows the results with example
then he erase the "le" -> 
"examp" -> if the previous request is not completed, cancel it -> make request for "examp" and show the data in table view!

P.S。从我发现的另一个答案

func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
    // to limit network activity, reload half a second after last key press.
    NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(self.reload), object: nil)
    self.perform(#selector(self.reload), with: nil, afterDelay: 0.5)
}
func reload() {
    print("Doing things")
}

虽然如果我试图替换&#34; self.reload&#34;我的功能,我收到一个错误 cannot convert value of type () to expected argument type selector

3 个答案:

答案 0 :(得分:11)

将DispatchWorkItem与Swift 4一起使用!

// Add a searchTask property to your controller
var searchTask: DispatchWorkItem?


// then in your search bar update method

// Cancel previous task if any
self.searchTask?.cancel()

// Replace previous task with a new one
let task = DispatchWorkItem { [weak self] in
    self?.sendSearchRequest() 
}
self.searchTask = task

// Execute task in 0.75 seconds (if not cancelled !)
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.75, execute: task)

希望它有所帮助!

答案 1 :(得分:1)

您的错误是因为您可能忘记了#selector()部分。

以下是它的外观:

func searchBar() { 
    NSObject.cancelPreviousPerformRequests(withTarget: self,    
                                           selector: #selector(self.getSearch(completed:searchString:)), 
                                           object: nil) 

    perform(#selector(self.getSearch(completed:searchString:)), 
            with: nil, afterDelay: 0.5) }

您收到错误是因为您未将功能括在#selector

现在,至于参数,这里有一个函数:

perform(#selector(getSearch:completion:searchString), with: <some completion>, with: "search string")

答案 2 :(得分:0)

  • 免责声明:我是作者。

如果您需要基于 vanilla Foundation 的实时搜索限制功能,
如果你只想要一个线性 API 而不涉及反应式、组合、定时器、NSObject 取消和任何复杂的东西,

Throttler 可以成为完成工作的正确工具。

您可以使用节流功能而不会出现以下反应:

import Throttler

Throttler.go {
    self.sendSearchRequest() 
}

// That's all.

另一个例子:

import Throttler

for i in 1...1000 {
    Throttler.go {
        print("throttle! > \(i)")
    }
}

// throttle! > 1000