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

Posted

技术标签:

【中文标题】如何在 Swift 中创建自动完成文本字段【英文标题】:How to create autocomplete text field in Swift 【发布时间】:2016-06-08 08:16:01 【问题描述】:

我希望能够在 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()

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

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

以逗号分隔,第一个参数为client ID,第二个参数为客户端名称。 John 是名称,因此它应该出现在自动完成建议中,如果选中,则会将 clientTextField 的文本设置为 John

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

我不知道该怎么做。用户可能正在输入但尚未完成,而可能已经发送了多个查询。

【问题讨论】:

一些库:1.github.com/hoteltonight/HTAutocompleteTextField 2.github.com/Mazyod/MJAutoComplete 【参考方案1】:

我在我的应用程序中做了类似的事情来查找联系人。我将把它伪编码出来让你理解这个概念:

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()
    

【讨论】:

【参考方案2】:

在这里使用类似 Trie 的结构将是一个更好的选择。根据输入的字符串,trie 将返回以输入的字符串开头的***关键字(比如说 10)。在服务器端实现这个 trie 会更好。当 UI 进行 http 调用时,将在服务器端进行计算,服务器会将 top 结果发送到 UI。然后,UI 将使用新数据更新 TableView。

您也可以使用 hashmap/dictionary 执行此操作,但性能会更差。当您要检查数千或数百万个字符串时,使用 trie/前缀树方法将为您提供最佳性能。

【讨论】:

以上是关于如何在 Swift 中创建自动完成文本字段的主要内容,如果未能解决你的问题,请参考以下文章

如何根据句子结构在输入字段中创建多个自动完成?

使用下拉列表在 Java 中创建一个自动完成文本框

在 Google App Engine 中创建表单自动完成

在 swift 中使用 tableview 和数组过滤器自动完成文本字段

如何在 ASP.NET 中制作自动完成文本框?

如何在HTML / Javascript中创建可编辑的组合框?