搜索结果未通过自动完成更新
Search results not updating with autocompletion
我正在 swift 中构建一个需要能够搜索城市的应用程序,我希望搜索与自动完成一起使用。
所以我开始在 xib 中创建一个视图控制器,其中包含一个带有关联控制器的 UISearch 栏。我为视图控制器编写的 class 如下:
import UIKit
class LocationViewController: UIViewController, UISearchBarDelegate, UITableViewDataSource, UITableViewDelegate, UISearchControllerDelegate {
// MARK: - Properties
var dirty: Bool = false
var loading: Bool = false
var suggestions: Array<String> = [] {
didSet {
searchDisplayController?.searchResultsTableView.reloadData()
}
}
// MARK: - Initialization
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func viewDidLoad() {
searchDisplayController?.searchBar.placeholder = "Ville ou adresse"
}
// MARK: - UISearchBarDelegate
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
if countElements(searchText) > 0 {
if (loading) {
dirty = true
} else {
loadSearchSuggestions()
}
}
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
suggestions = []
}
// MARK: - Search backend
func loadSearchSuggestions() {
loading = true
var query = searchDisplayController?.searchBar.text
var urlEncode = query!.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())!
var urlString = "https://maps.googleapis.com/maps/api/place/autocomplete/json?key=MYAPIKEY&components=country:FR&input=\(urlEncode)"
var request = NSURLRequest(URL: NSURL(string: urlString)!)
var session = NSURLSession.sharedSession()
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
if (error != nil) {
self.loading = false
println(error.localizedDescription)
return
}
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers, error: &err) as Dictionary<String,AnyObject>
var predictions = jsonResult["predictions"] as Array<AnyObject>
var currentSug: Array<String> = []
for prediction in predictions {
var predDict = prediction as Dictionary<String, AnyObject>
var adress = predDict["description"] as String
currentSug.append(adress)
}
if err != nil {
println("JSON Error in search \(err!.localizedDescription)")
return
}
self.suggestions = currentSug
if self.dirty {
self.dirty = false
self.loadSearchSuggestions()
}
self.loading = false
})
task.resume()
}
// MARK: - UITableViewDataSource
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "suggestCell"
var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as UITableViewCell?
if cell == nil {
cell = UITableViewCell(style: .Default, reuseIdentifier: cellIdentifier)
}
if suggestions.count > 0 {
cell!.textLabel!.text = suggestions[indexPath.row]
}
return cell!
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return suggestions.count
}
}
一切正常,直到一点。当我在我的搜索框中写一封信时,该请求有效并且我得到一个存储在我的建议 var.
中的结果
唯一的问题是:包含结果的 table 视图没有按应有的方式重新加载(如 suggestions var 的 didSet 中指定的那样)。除非我尝试滚动空列表。
现在,如果我键入第二个字符,我的 table 视图会显示仅键入一个字符时的结果。如果我尝试滚动,那么我会得到正确的结果。
非常感谢您抽出时间回答我的问题。我可能在我的代码中犯了错误,因为我对 swift 和一般编程还是很陌生。
答案很简单,我没看到!
Google API 的查询是异步完成的,另一方面 UI 的更新需要同步完成。
这是缺少的代码,就在 LoadSearchSuggestions
中的 self.loading = false
之后:
self.loading = false
dispatch_async(dispatch_get_main_queue(), {
searchDisplayController?.searchResultsTableView.reloadData()
})
这就是诀窍,希望它能帮助别人!
我正在 swift 中构建一个需要能够搜索城市的应用程序,我希望搜索与自动完成一起使用。
所以我开始在 xib 中创建一个视图控制器,其中包含一个带有关联控制器的 UISearch 栏。我为视图控制器编写的 class 如下:
import UIKit
class LocationViewController: UIViewController, UISearchBarDelegate, UITableViewDataSource, UITableViewDelegate, UISearchControllerDelegate {
// MARK: - Properties
var dirty: Bool = false
var loading: Bool = false
var suggestions: Array<String> = [] {
didSet {
searchDisplayController?.searchResultsTableView.reloadData()
}
}
// MARK: - Initialization
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func viewDidLoad() {
searchDisplayController?.searchBar.placeholder = "Ville ou adresse"
}
// MARK: - UISearchBarDelegate
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
if countElements(searchText) > 0 {
if (loading) {
dirty = true
} else {
loadSearchSuggestions()
}
}
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
suggestions = []
}
// MARK: - Search backend
func loadSearchSuggestions() {
loading = true
var query = searchDisplayController?.searchBar.text
var urlEncode = query!.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())!
var urlString = "https://maps.googleapis.com/maps/api/place/autocomplete/json?key=MYAPIKEY&components=country:FR&input=\(urlEncode)"
var request = NSURLRequest(URL: NSURL(string: urlString)!)
var session = NSURLSession.sharedSession()
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
if (error != nil) {
self.loading = false
println(error.localizedDescription)
return
}
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers, error: &err) as Dictionary<String,AnyObject>
var predictions = jsonResult["predictions"] as Array<AnyObject>
var currentSug: Array<String> = []
for prediction in predictions {
var predDict = prediction as Dictionary<String, AnyObject>
var adress = predDict["description"] as String
currentSug.append(adress)
}
if err != nil {
println("JSON Error in search \(err!.localizedDescription)")
return
}
self.suggestions = currentSug
if self.dirty {
self.dirty = false
self.loadSearchSuggestions()
}
self.loading = false
})
task.resume()
}
// MARK: - UITableViewDataSource
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "suggestCell"
var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as UITableViewCell?
if cell == nil {
cell = UITableViewCell(style: .Default, reuseIdentifier: cellIdentifier)
}
if suggestions.count > 0 {
cell!.textLabel!.text = suggestions[indexPath.row]
}
return cell!
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return suggestions.count
}
}
一切正常,直到一点。当我在我的搜索框中写一封信时,该请求有效并且我得到一个存储在我的建议 var.
中的结果唯一的问题是:包含结果的 table 视图没有按应有的方式重新加载(如 suggestions var 的 didSet 中指定的那样)。除非我尝试滚动空列表。
现在,如果我键入第二个字符,我的 table 视图会显示仅键入一个字符时的结果。如果我尝试滚动,那么我会得到正确的结果。
非常感谢您抽出时间回答我的问题。我可能在我的代码中犯了错误,因为我对 swift 和一般编程还是很陌生。
答案很简单,我没看到!
Google API 的查询是异步完成的,另一方面 UI 的更新需要同步完成。
这是缺少的代码,就在 LoadSearchSuggestions
中的 self.loading = false
之后:
self.loading = false
dispatch_async(dispatch_get_main_queue(), {
searchDisplayController?.searchResultsTableView.reloadData()
})
这就是诀窍,希望它能帮助别人!