如何在Swift中创建自动完成文本框

18
我想要创建的是一个iOS中的自动完成文本框。
我有一个选择客户的表单,在该表单中,用户必须使用文本字段选择客户。我的要求是,当用户在文本字段上输入前三个字母时,某些服务应运行远程网络服务查询并将查询结果作为自动完成建议提供给用户。
以下是我目前的应用程序代码(仅限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()
}

这是我的Web服务提供的JSON输出。

["123,John", "343,Smith", "345,April"]

第一个参数是“客户端ID”,第二个参数是客户的姓名,用逗号分隔。 "John" 是客户的名字,因此应在自动完成建议中显示,如果选择它,将把 "clientTextField" 的文本设置为 "John"。

"clientTextField" 的当前文本内容作为 GET 参数传递给我的 Web 服务。

我不知道如何做到这一点。用户可能正在输入但尚未完成,而多个查询可能已经被发送。


一些库:1. https://github.com/hoteltonight/HTAutocompleteTextField 2. https://github.com/Mazyod/MJAutoComplete - Warif Akhand Rishi
2个回答

4

我在我的联系人查找应用程序中做了类似的事情。以下是我为您提供的伪代码,以便您理解概念:

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
使用类似Trie的结构会是更好的选择。基于输入的字符串,Trie将返回以该字符串开头的前10个关键字。在服务器端实现此Trie更好。当UI进行http调用时,计算将在服务器端完成,并且服务器将向UI发送顶部结果。然后,UI将使用新数据更新TableView。
您也可以使用哈希映射/字典来实现此操作,但性能会更差。当您有数千或数百万个字符串要检查时,使用Trie /前缀树方法将为您提供最佳性能。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接