我希望能够创建的是iOS中的自动完整文本字段。
我有一个用于选择客户端的表单,其中用户必须使用文本字段选择一次客户端。我想要发生的是当用户在文本字段上写前三个字母时,我想要一些服务使用输入的文本运行远程Web服务查询,并将查询结果显示为自动完成建议。
以下是我的应用程序的当前代码(仅限iPad)。
import UIKit
class AddClientViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var clientTextField: UITextField!
var foundList = [String]()
override func viewDidLoad() {
super.viewDidLoad()
let listUrlString = "http://bla.com/myTextField.php?field=\(clientTextField)"
let myUrl = NSURL(string: listUrlString);
let request = NSMutableURLRequest(URL:myUrl!);
request.HTTPMethod = "GET";
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
print(error!.localizedDescription)
dispatch_sync(dispatch_get_main_queue(),{
AWLoader.hide()
})
return
}
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSArray
if let parseJSON = json {
self.foundList = parseJSON as! [String]
}
} catch {
print(error)
}
}
task.resume()
}
这是我的网络服务提供的json输出。
["123,John", "343,Smith", "345,April"]
用逗号分隔,第一个参数是client ID
,第二个参数是客户端的名称。 John
是名称,因此应在自动完成建议中显示,如果选中,则会将clientTextField
的文字设置为John
。
clientTextField
的当前文本内容作为GET参数传递给我的webservice。
我不知道该怎么做。用户可能正在键入但尚未完成,而多个查询可能已经发送过。
感谢。
iwillnot:我在下面的Swift上收集了对自动完整文本字段的引用。
https://github.com/mnbayan/AutocompleteTextfieldSwift(2016年7月)
http://github.com/Mazyod/MJAutoComplete(2015年7月)
http://github.com/hoteltonight/HTAutocompleteTextField(2015年3月)
https://github.com/gaurvw/MPGTextField(2014年6月)
自2016年8月19日起的最后更新订购。
答案 0 :(得分:2)
我在我的应用中做了类似的事情来查找联系人。我将伪代码给你理解这个概念:
1)捕获最终用户输入文本字段的字符
2)在输入的某些字符数决定查询服务器以返回所有匹配的条目 - 选择您熟悉的字符数(我选择了大约3-4个字符)。更少的回报,更多的回报不那么明显......取决于你,性能和用户体验的考虑因素。
3)将此服务器查询的结果放入客户端的数组中。这将是您的超集,您将从中向用户提供建议。
4)在每个后续字符输入文本字段后,您现在将按此处输入的字符串过滤数组(array.filter())。
5)tableView.reloadData()针对输入的每个字符的过滤数组。
6)我使用dataFlag变量来确定要在tableview中显示的数据源,具体取决于用户正在做什么。
注意:您只需查询服务器一次以最小化性能影响
// this function is called automatically when the search control get user focus
func updateSearchResults(for searchController: UISearchController) {
let searchBar = searchController.searchBar
if searchBar.text?.range(of: "@") != nil {
self.getUserByEmail(searchBar.text!)
}
if searchController.searchBar.text?.characters.count == 0 && dataFlag != "showParticipants" {
dataFlag = "showInitSearchData"
self.contacts.removeAll()
self.participantTableView.reloadData()
}
if dataFlag == "showInitSearchData" && searchController.searchBar.text?.characters.count == 2 {
self.loadInitialDataSet() {
self.dataFlag = "showFilteredSearchData"
}
}
if dataFlag == "showFilteredSearchData" {
self.filterDataForSearchString()
}
}
// filter results by textfield string
func filterDataForSearchString() {
let searchString = searchController.searchBar.text
self.filteredContacts = self.contacts.filter({
(contact) -> Bool in
let contactText: NSString = "\(contact.givenName) \(contact.familyName)" as NSString
return (contactText.range(of: searchString!, options: NSString.CompareOptions.caseInsensitive).location) != NSNotFound
})
DispatchQueue.main.async {
self.participantTableView.reloadData()
}
}
答案 1 :(得分:1)
在这里使用类似Trie的结构将是更好的选择。根据输入的字符串,trie将返回以输入的字符串开头的顶级关键字(假设为10)。在服务器端实施此尝试更好。当UI进行http调用时,将在服务器端进行计算,并且服务器会将最重要的结果发送到UI。然后,UI将使用新数据更新TableView。
您也可以使用hashmap / dictionary进行此操作,但性能会更差。当您要检查成千上万个字符串时,使用特里/前缀树方法将为您带来最佳性能。