UISearchController 仅在单击搜索按钮时更新
UISearchController only update on search button click
我有一个 UISearchController,它被配置为搜索大量数据。因此,当我在搜索栏中输入内容时,需要很长时间才能真正输入我的搜索内容。它对搜索字段中的每个字符条目执行搜索比较,这非常慢。
我想知道如何解决这个问题。我的想法是:
- 仅在用户完成输入并点击搜索按钮后执行搜索
- 在后台线程上执行搜索,释放主线程用于键盘输入
我想使用方法一
但我似乎无法弄清楚如何使用新的 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)
}
您可以使用委托方法 searchBarSearchButtonPressed:
来监视何时按下搜索按钮。在执行此委托方法时设置一个标志,然后在 searchBarTextDidChange:
方法中您可以检查此标志以查看是否应执行搜索。当然,这只会在用户按下搜索键后进行搜索,而且大多数人都希望在输入时看到一些事情发生。
如果您只想在用户单击 "Search" 按钮时执行搜索 - 这对于更大和更慢的访问数据集来说似乎既明智又合理,您可以这样做:
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.searchBar.delegate = self
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.sizeToFit()
tableView.tableHeaderView = searchController.searchBar
definesPresentationContext = true
searchController.hidesNavigationBarDuringPresentation = false
self.tableView.reloadData()
}
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
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()
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
}
主要区别在于设置 searchController.searchBar.delegate = self,并将您的搜索代码放在 searchBarSearchButtonClicked 函数中而不是 updateSearchResultsForSearchController - 现在应该什么也不做。
对于任何错误,我深表歉意,我使用 Xcode v7.0.1 Objective-C 测试了此代码,然后转置了更改。
我有一个 UISearchController,它被配置为搜索大量数据。因此,当我在搜索栏中输入内容时,需要很长时间才能真正输入我的搜索内容。它对搜索字段中的每个字符条目执行搜索比较,这非常慢。
我想知道如何解决这个问题。我的想法是:
- 仅在用户完成输入并点击搜索按钮后执行搜索
- 在后台线程上执行搜索,释放主线程用于键盘输入
我想使用方法一 但我似乎无法弄清楚如何使用新的 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)
}
您可以使用委托方法 searchBarSearchButtonPressed:
来监视何时按下搜索按钮。在执行此委托方法时设置一个标志,然后在 searchBarTextDidChange:
方法中您可以检查此标志以查看是否应执行搜索。当然,这只会在用户按下搜索键后进行搜索,而且大多数人都希望在输入时看到一些事情发生。
如果您只想在用户单击 "Search" 按钮时执行搜索 - 这对于更大和更慢的访问数据集来说似乎既明智又合理,您可以这样做:
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.searchBar.delegate = self
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.sizeToFit()
tableView.tableHeaderView = searchController.searchBar
definesPresentationContext = true
searchController.hidesNavigationBarDuringPresentation = false
self.tableView.reloadData()
}
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
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()
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
}
主要区别在于设置 searchController.searchBar.delegate = self,并将您的搜索代码放在 searchBarSearchButtonClicked 函数中而不是 updateSearchResultsForSearchController - 现在应该什么也不做。 对于任何错误,我深表歉意,我使用 Xcode v7.0.1 Objective-C 测试了此代码,然后转置了更改。