Ios 让autocomplete在swift中工作

Ios 让autocomplete在swift中工作,ios,swift,autocomplete,Ios,Swift,Autocomplete,我正在尝试实现自动完成,但找不到在Swift中有效的示例。下面,我尝试转换2010年的示例代码。最后,代码进行了编译,但是包含可能的补全的表没有出现,我也没有经验去理解为什么shouldChangeCharactersInRange没有取消隐藏它 class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate { @IBOutlet weak var

我正在尝试实现自动完成,但找不到在Swift中有效的示例。下面,我尝试转换2010年的示例代码。最后,代码进行了编译,但是包含可能的补全的表没有出现,我也没有经验去理解为什么shouldChangeCharactersInRange没有取消隐藏它

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {

@IBOutlet weak var textField: UITextField!
let autocompleteTableView = UITableView(frame: CGRectMake(0,80,320,120), style: UITableViewStyle.Plain)

var pastUrls = ["Men", "Women", "Cats", "Dogs", "Children"]
var autocompleteUrls = [String]()

override func viewDidLoad() {
    super.viewDidLoad()

    autocompleteTableView.delegate = self
    autocompleteTableView.dataSource = self
    autocompleteTableView.scrollEnabled = true
    autocompleteTableView.hidden = true
}

func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool
{
    autocompleteTableView.hidden = false
    var substring = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)

    searchAutocompleteEntriesWithSubstring(substring)
    return true     // not sure about this - could be false
}

func searchAutocompleteEntriesWithSubstring(substring: String)
{
    autocompleteUrls.removeAll(keepCapacity: false)
    var indexOfPastUrls = 0

    for curString in pastUrls
    {
        let substringRange = curString.rangeOfString(curString)

        if (indexOfPastUrls  == 0)
        {
            autocompleteUrls.append(curString)
        }
        indexOfPastUrls = indexOfPastUrls + 1
    }
    autocompleteTableView.reloadData()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return autocompleteUrls.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let autoCompleteRowIdentifier = "AutoCompleteRowIdentifier"
    var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier(autoCompleteRowIdentifier, forIndexPath: indexPath) as UITableViewCell
    let index = indexPath.row as Int

    cell.textLabel.text = autocompleteUrls[index]
    return cell
}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let selectedCell : UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
    textField.text = selectedCell.textLabel.text        
}
}

SearchAutoCompleteTentriesWithSubString
函数内容替换为以下内容。我希望它能帮助你

func searchAutocompleteEntriesWithSubstring(substring: String)
{
    autocompleteUrls.removeAll(keepCapacity: false)

    for curString in pastUrls
    {
        var myString:NSString! = curString as NSString

        var substringRange :NSRange! = myString.rangeOfString(substring)

        if (substringRange.location  == 0)
        {
            autocompleteUrls.append(curString)
        }
    }

    autocompleteTableView.reloadData()
}

该表未出现,因为UITextField委托未在viewDidLoad中设置为self。最后一个问题是表格没有显示自动完成结果,但这也是固定的。Ray Wenderlich的基本Objective-C自动完成教程已转换为Swift:

class ViewController: UIViewController, UITextFieldDelegate, UITableViewDelegate,   UITableViewDataSource {

@IBOutlet weak var textField: UITextField!
@IBOutlet var autocompleteTableView: UITableView!

// @IBOutlet weak var autocompleteTableView = UITableView(frame: CGRectMake(0,80,320,120), style: UITableViewStyle.Plain)

var pastUrls = ["Men", "Women", "Cats", "Dogs", "Children"]
var autocompleteUrls = [String]()

override func viewDidLoad() {
    super.viewDidLoad()

    textField.delegate = self

    autocompleteTableView!.delegate = self
    autocompleteTableView!.dataSource = self
    autocompleteTableView!.scrollEnabled = true
    autocompleteTableView!.hidden = true
}

func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool
{
    println("banana")
    autocompleteTableView!.hidden = false
    var substring = (self.textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)

    searchAutocompleteEntriesWithSubstring(substring)
    return true
}

func searchAutocompleteEntriesWithSubstring(substring: String)
{
    autocompleteUrls.removeAll(keepCapacity: false)
    println(substring)

    for curString in pastUrls
    {
        println(curString)
        var myString: NSString! = curString as NSString
        var substringRange: NSRange! = myString.rangeOfString(substring)
        if (substringRange.location == 0)
        {
            autocompleteUrls.append(curString)
        }
    }

    autocompleteTableView!.reloadData()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return autocompleteUrls.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    let autoCompleteRowIdentifier = "AutoCompleteRowIdentifier"
    var cell = tableView.dequeueReusableCellWithIdentifier(autoCompleteRowIdentifier) as? UITableViewCell

    if let tempo1 = cell
    {
        let index = indexPath.row as Int
        cell!.textLabel.text = autocompleteUrls[index]
    } else
    {
        cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: autoCompleteRowIdentifier)
    }
    return cell!
}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let selectedCell : UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
    textField.text = selectedCell.textLabel.text
}

}

这里有一种方法可以添加多个标记,它基于像twitter一样键入的“#”

变量typedSubstring是全局子字符串

  func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool {

autocompleteTableView!.hidden = false
var changedText = (self.textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
var items = changedText.componentsSeparatedByString("#")

if (items.count > 0) {
  typedSubstring  = "#" + items.lastObject as NSString

  self.searchAutocompleteEntriesWithSubstring(typedSubstring)
}

return true
}

改进了DrWhat’s解决方案,因此当您选择单元格时,它会在用户已键入的位置后正确地追加该单元格

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) 
let selectedCell : UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!

let selectedText = selectedCell.textLabel?.text as String!

// Remove what has been typed already
let trimmedString = selectedText.stringByReplacingOccurrencesOfString(typedSubstring, withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)

var currentTextField = textField.text

// then append to what has been typed
textField.text = currentTextField + trimmedString

iOS 9.0和Swift 2的固定版本:

import UIKit

class UIAutoCompleteTextField: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {
    @IBOutlet weak
    var textField: UITextField!
        let autocompleteTableView = UITableView(frame: CGRectMake(0, 80, 320, 120), style: UITableViewStyle.Plain)

    var pastUrls = ["Men", "Women", "Cats", "Dogs", "Children"]
    var autocompleteUrls = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()

        autocompleteTableView.delegate = self
        autocompleteTableView.dataSource = self
        autocompleteTableView.scrollEnabled = true
        autocompleteTableView.hidden = true
    }

    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) - > Bool {
        autocompleteTableView.hidden = false
        let substring = (textField.text!as NSString).stringByReplacingCharactersInRange(range, withString: string)

        searchAutocompleteEntriesWithSubstring(substring)
        return true // not sure about this - could be false
    }

    func searchAutocompleteEntriesWithSubstring(substring: String) {
        autocompleteUrls.removeAll(keepCapacity: false)

        for curString in pastUrls {
            let myString: NSString! = curString as NSString

            let substringRange: NSRange! = myString.rangeOfString(substring)

            if (substringRange.location == 0) {
                autocompleteUrls.append(curString)
            }
        }

        autocompleteTableView.reloadData()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) - > Int {
        return autocompleteUrls.count
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) - > UITableViewCell {

        let autoCompleteRowIdentifier = "AutoCompleteRowIdentifier"
        let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(autoCompleteRowIdentifier, forIndexPath: indexPath) as UITableViewCell
        let index = indexPath.row as Int

        cell.textLabel!.text = autocompleteUrls[index]
        return cell
    }

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        let selectedCell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath) !
            textField.text = selectedCell.textLabel!.text
    }
}

对于未来的人来说,这可能需要使用Swift 2在autocomplete texfield上工作,@dane提供的代码工作得很好。但你必须改变这一行:

let cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier(autoCompleteRowIdentifier, forIndexPath: indexPath) as UITableViewCell

此外,您可能会注意到,it是区分大小写的,如果默认情况下输入小写字符串(例如cats),它将不起作用。因此,要解决此问题,可以替换为将选项“CaseSensitiveSearch”添加到substringRange声明中(在func SearchAutoCompleteTentriesWithSubString中)。它应该是这样的:

let substringRange :NSRange! = myString.rangeOfString(substring,options [.CaseInsensitiveSearch])

希望它能帮你节省一天

让它在下面工作。大写/小写最初将其丢弃。我用它来自动完成国家名称

import UIKit

class billingAddressViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {


    @IBOutlet var countryTextField: UITextField!
    @IBOutlet var countryTableView: UITableView!

    var autocompleteCountries = [String]()

    // Get list of countries
    let countries = NSLocale.ISOCountryCodes().map { (code:String) -> String in
        let id = NSLocale.localeIdentifierFromComponents([NSLocaleCountryCode: code])
        return NSLocale(localeIdentifier: "en_US").displayNameForKey(NSLocaleIdentifier, value: id) ?? "Country not found for code: \(code)"
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        countryTextField.delegate = self

        countryTableView!.delegate = self
        countryTableView!.dataSource = self
        countryTableView!.scrollEnabled = true
        countryTableView!.hidden = true
    }

    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {

        print("text field has changed")
        countryTableView!.hidden = false

        let substring = (self.countryTextField.text! as NSString).stringByReplacingCharactersInRange(range, withString: string)
        print(substring)
        searchAutocompleteEntriesWithSubstring(substring)
        return true
    }

    func searchAutocompleteEntriesWithSubstring(substring: String) {
        autocompleteCountries.removeAll(keepCapacity: false)
        print(substring)

        for curString in countries {
            //print(curString)
            let myString: NSString! = curString.lowercaseString as NSString
            let substringRange: NSRange! = myString.rangeOfString(substring.lowercaseString)
            if (substringRange.location == 0) {
                autocompleteCountries.append(curString)
            }
        }

        countryTableView!.reloadData()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return autocompleteCountries.count
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let autoCompleteRowIdentifier = "AutoCompleteRowIdentifier"
        var cell = tableView.dequeueReusableCellWithIdentifier(autoCompleteRowIdentifier) as UITableViewCell!

        if let tempo1 = cell {
            let index = indexPath.row as Int
            cell!.textLabel!.text = autocompleteCountries[index]
        }

        else {
            cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: autoCompleteRowIdentifier)
        }

        return cell!
    }

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        let selectedCell : UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
        countryTextField.text = selectedCell.textLabel!.text
        countryTableView.hidden = true
    }

}

我编写了一个教程,里面有很多关于如何重新创建这个已经有6年历史的教程的图片


matthewhsingleton.com/coding-with-a-ruber-ducky/2016/5/26/…-添加了RubberDucky4444表视图,但没有故事板

class ViewController: UIViewController  , UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {


@IBOutlet weak var textField: UITextField!

var autocompleteTableView: UITableView!
var pastUrls = ["Men", "Women", "Cats", "Dogs", "Children","aaaaaaaaa","aaaaaaaaaaaaaaaaaaa","aaaaaaaaa","a","aa","aaa"]
var autocompleteUrls = [String]()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    autocompleteTableView = UITableView(frame: CGRectMake(self.textField.bounds.minX,self.textField.bounds.maxY,self.textField.bounds.width,self.textField.bounds.height * 4), style: UITableViewStyle.Plain)

    textField.delegate = self

    autocompleteTableView.delegate = self
    autocompleteTableView.dataSource = self
    autocompleteTableView.scrollEnabled = true
    autocompleteTableView.hidden = false

    autocompleteTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
    self.view.addSubview(autocompleteTableView)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool
{
    autocompleteTableView.hidden = false
    var substring = (self.textField.text! as NSString).stringByReplacingCharactersInRange(range, withString: string)

    searchAutocompleteEntriesWithSubstring(substring)
    return true      // not sure about this - could be false
}

func searchAutocompleteEntriesWithSubstring(substring: String)
{
    autocompleteUrls.removeAll(keepCapacity: false)

    for curString in pastUrls
    {
        var myString:NSString! = curString as NSString

        var substringRange :NSRange! = myString.rangeOfString(substring)

        if (substringRange.location  == 0)
        {
            autocompleteUrls.append(curString)
        }
    }

    autocompleteTableView.reloadData()
    //autocompleteTableView.hidden = false
}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return autocompleteUrls.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

            let autoCompleteRowIdentifier = "cell"
            var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier(autoCompleteRowIdentifier, forIndexPath: indexPath) as UITableViewCell
            let index = indexPath.row as Int

            cell.textLabel!.text = autocompleteUrls[index]



            return cell




}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let selectedCell : UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
    textField.text = self.autocompleteUrls[indexPath.row]

    self.autocompleteTableView.hidden = true
}











 }

这篇文章帮助了我,谢谢,以防你们在swift 3中使用google places API,并且需要不区分大小写。这里是更新后的代码,您只需输入:

let subStringRange : NSRange! = myString.range(of: substring, options: .caseInsensitive)

用以下函数替换
cellforrowatinexpath


为了简化这项工作,这里有一个很好的库:

Add
view.addSubview(autocompleteTableView)


视图中加载
。它会起作用。

子字符串范围类型是NSRange而不是let,然后必须检查子字符串范围。位置==0,而不是自动完成URL。追加(curString)是-我引入了indexOfPastUrls而不是子字符串范围。位置==0,因为我无法确定如何使子字符串范围类型为NSRange。我已尝试指定let substringRange:NSRange并强制转换方程的另一面。@DrWhat..如何以及何时调用“func textField(textField:UITextField!,shouldChangeCharactersInRange:NSRange,replacementString:string!)->Bool”“method?@dhaval shah-这是一个委托方法,所以我的理解是,在输入字符之前,它会自动被调用。是的,谢谢你的回复!这看起来好多了。因此,在Swift myString.rangeOfString(substring)中,可以使用myString:NSString和substring:String。我不知道你是怎么知道的,但是谢谢你!!!如果我有足够的声誉,我会投票支持这个。不幸的是,我的自动完成表还没有出现,所以我希望你不介意我把问题留着。我最后自己回答了这个问题,所以我认为你做了困难的部分。再次感谢。感谢您提供的简单而精彩的解决方案。。。!它很有魅力。。当tableview有多个分区且每个分区都有多行时,如何实现这一点……?我遇到一个错误:在展开
autocompleteTableView!时发现为零!。委派=自我
。您是否使用Interface Builder创建了
autocompleteTableView
?如果没有在任何其他位置完成,我会在viewDidLoad中将textField.delegate分配给self。为了其他人的利益,我还要指出,上面的代码假设一个现有的单元原型。如果您想使用默认单元格运行它,我会在CellForRowatineXpath方法中使用以下内容:cell=UITableViewCellStyle(style:UITableViewCellStyle.default,reuseIdentifier:cellIdentifier)dane,感谢这段代码,非常有用。仅供参考,只需使用interface builder添加一个tableview并将其连接到名为autocompleteTableView的IBOutlet就可以轻松得多。根据@LNI注释,我已在interface builder的文本字段下直接添加了一个tableview,并将其连接到名为autocompleteTableView的IBOutlet。这允许我设置原型单元的重用标识符以及tableview本身的自动布局约束。这种方法在Xcode 7.2和Swift 2.1中适用。在Swift 2.1.1中,我必须调整行的语法,使搜索在@edess示例中不区分大小写。新语法如下:let substringRange:NSRange!=myString.rangeOfString(子字符串,选项:.CaseInsensitiveSearch)使用
let cell=UITableViewCell(style:UITableViewCellStyle.Default,reuseIdentifier:cellIdentifier)
每次都会创建一个新的单元格,这会降低应用程序的速度并消耗大量内存。最好使用@dane的方法,但使用以下方法在tableView中注册重用标识符:
func registerClass(\uCellClass:AnyClass?,forCellReuseIdentifier identifier:String)
大家好,我使用的是搜索API,虽然这在理论上可以回答问题,但要在这里包括答案的基本部分,并提供链接供参考。嗨,欢迎来到Stack Overflow,谢谢你的第一个答案。为了让答案对其他人更有用,最好的做法是让你的答案更详细,例如包括一个显示wh的代码示例
let subStringRange : NSRange! = myString.range(of: substring, options: .caseInsensitive)
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    var cell = UITableViewCell()
    var data = autocompleteUrls[indexPath.row]
    cell.textLabel?.text = data as String
    return cell
}