ios 快速自动完成工作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26885438/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 03:36:10  来源:igfitidea点击:

Getting autocomplete to work in swift

iosswiftautocomplete

提问by DrWhat

I am trying to implement autocompletion, but can't find an example that works in Swift. Below, I'm tring to convert Ray Wenderlich's autocompletion tutorialand example code from 2010. Finally, the code compiles, but the table containing possible completions does not appear, and I don't have the experience to see why it is not unhidden by shouldChangeCharactersInRange.

我正在尝试实现自动完成,但找不到适用于 Swift 的示例。下面,我正在尝试转换Ray Wenderlich 的自动补全教程和 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        
}
}

采纳答案by Tamnna

Replace your searchAutocompleteEntriesWithSubstringfunction content with the one below. I hope it would help you.

将您的searchAutocompleteEntriesWithSubstring功能内容替换为以下内容。我希望它会帮助你。

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

回答by DrWhat

The table was not appearing because the UITextField delegate was not to self in viewDidLoad. There was another final issue with the table not showing the autocompletion results, but this is also fixed. Ray Wenderlich's basic Objective-C autocompletion tutorial converted to Swift:

该表没有出现,因为 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
}

}

}

回答by RubberDucky4444

I put together a tutorial that is full of pictures on how to recreate this now 6 year old tutorial

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

matthewhsingleton.com/coding-with-a-rubber-ducky/2016/5/26/… – RubberDucky4444

matthewhsingleton.com/coding-with-a-rubber-ducky/2016/5/26/... – RubberDucky4444

回答by dane

Fixed for iOS 9.0 and Swift 2:

已针对 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
    }
}

回答by Edess Elder

For future guys, that might get to work on autocomplete texfield with Swift 2, the code provided by @dane works well. but you have to change this line:

对于未来的人,这可能会使用 Swift 2 处理自动完成 texfield,@dane 提供的代码运行良好。但你必须改变这一行:

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

by

经过

let cell = UITableViewCell(style: UITableViewCellStyle.Default , reuseIdentifier: cellIdentifier)

Also, you might notice that the it is case sensitive, and doesn't work if you enter lowercase string (e.g cats) by default. So to solve this issue you can replace add the option "CaseSensitiveSearch" to the substringRange declaration (in the func searchAutocompleteEntriesWithSubstring). it should look like:

此外,您可能会注意到它区分大小写,并且如果您默认输入小写字符串(例如,cats)则不起作用。因此,要解决此问题,您可以替换将选项“CaseSensitiveSearch”添加到 substringRange 声明(在 func searchAutocompleteEntriesWithSubstring 中)。它应该看起来像:

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

Hope it will help you save one day!!!

希望它可以帮助您节省一天!!!

回答by ramblin

Got it working with the below. The upper/lower case threw it off initially. I'm using it to autocomplete country names...

得到它与下面的工作。大写/小写字母一开始就把它扔掉了。我正在使用它来自动完成国家/地区名称...

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
    }

}

回答by Cloy

table view added without storyboard

添加了没有故事板的表格视图

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
}











 }

回答by vandit

Here's a way to add multiple tags based on "#" being typed in like twitter.

这是一种基于“#”添加多个标签的方法,例如 twitter。

Variable typedSubstring is the global substring.

变量 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

}

}

Improved on DrWhat's solution so that when you select a cell, it appends it correctly after where the user has already typed in.

改进了 DrWhat 的解决方案,以便当您选择一个单元格时,它会在用户已经输入的位置之后正确附加它。

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

回答by Navneet Prakash

This post helped me thanks, just in case you guys are working with google places API in swift 3 and you need case-insensitive here is the updated code you just have to put:

这篇文章帮助了我,谢谢,以防万一你们在 swift 3 中使用谷歌地点 API 并且你需要不区分大小写,这里是你只需要放置的更新代码:

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

回答by Parth

Replace cellForRowAtIndexPathwith following function

替换cellForRowAtIndexPath为以下函数

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

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