我有一個UISearchController配置爲搜索非常大的數據數組。因此,當我在搜索欄中輸入內容時,實際輸入我的搜索需要很長時間。它執行與搜索字段中每個字符條目的搜索比較,這是非常緩慢的。UISearchController只在搜索按鈕點擊更新
我想知道如何解決這個問題。我的想法是:
- 只有在用戶完成後輸入和點擊搜索按鈕
- 執行在後臺線程搜索,釋放了鍵盤輸入
主線程執行搜索我想使用方法1 但我似乎無法弄清楚如何用新的UISearchController做到這一點。
下面是我的相關項目代碼:
class AirportSearchTBVC: UITableViewController, UISearchResultsUpdating{
var airportData = [Dictionary<String, String>]()
var filteredData = [Dictionary<String, String>]()
var searchController = UISearchController()
override func viewDidLoad() {
super.viewDidLoad()
searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.sizeToFit()
tableView.tableHeaderView = searchController.searchBar
definesPresentationContext = true
searchController.hidesNavigationBarDuringPresentation = false
self.tableView.reloadData()
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
filteredData = []
let searchPredicate = NSPredicate(format: "SELF CONTAINS[cd] %@", searchController.searchBar.text!)
let array = (airportData as NSArray).filteredArrayUsingPredicate(searchPredicate)
filteredData = array as! [Dictionary<String, String>]
self.tableView.reloadData()
}
獎金問題 如果我搜索一個字符串,它不會出現要返回任何結果,如果字符串不完全匹配。例如:「orida」沒有找到「Florida」。我的搜索謂詞是不是應該使用CONTAINS來找到它?
更新 這段代碼幾乎可以工作,但它基本上在後臺線程上拋出了一堆東西,然後突然通過它。鍵盤現在是熱鬧,但似乎如果我就很快改變的事情在文本框中,同時駁回和重新進入搜索欄崩潰......
func updateSearchResultsForSearchController(searchController: UISearchController) {
appDel.backgroundThread(background: {
self.filteredData.removeAll(keepCapacity: false)
let searchPredicate = NSPredicate(format: "SELF CONTAINS[cd] %@", searchController.searchBar.text!)
let array = (self.airportData as NSArray).filteredArrayUsingPredicate(searchPredicate)
self.filteredData = array as! [Dictionary<String, String>]
},
completion: {
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}
});
}
更新2 打了一下後,有了它,我可以通過等待searchBar.text長度> = 3個字符以及確保字符數在updateSearchResultsForSearchController的1秒內沒有改變的方式使它正常工作:被調用。這些組合以及集成搜索按鈕執行命令應該可以解決我的問題。
func updateSearchResultsForSearchController(searchController: UISearchController) {
let startCount = searchController.searchBar.text!.length
delay(1) {
if searchController.searchBar.text!.length >= 3 && searchController.searchBar.text!.length == startCount{
self.view.addSubview(self.progressHud)
self.appDel.backgroundThread(background: {
self.filteredData.removeAll(keepCapacity: false)
let searchPredicate = NSPredicate(format: "SELF CONTAINS[cd] %@", searchController.searchBar.text!)
let array = (self.airportData as NSArray).filteredArrayUsingPredicate(searchPredicate)
self.filteredData = array as! [Dictionary<String, String>]
},
completion: {
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
self.progressHud.removeFromSuperview()
}
});
}
}
}
func delay(delay:Double, closure:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), closure)
}
有推薦的另一種策略嗎?考慮到人們期望看到不同的東西? – Charlie
那麼你可以把你的整個'searchBarTextDidChange:'執行放在GCD的後臺線程中,然後在更新'tableView'之前,你可以跳回主線程以確保UI更新快。 – pbush25
我已經更新了我的問題,嘗試執行您推薦的代碼,但實質上是因爲它在後臺線程中放入了很多請求,然後通過每個請求「突然跳出」......我真的很感謝您的幫助這裏:) – Charlie