最大长度UITextField

145

当我尝试使用如何使用Swift设置可以输入到UITextField中的最大字符数?时,我发现如果我使用了全部10个字符,我无法擦除字符。

我唯一能做的就是取消操作(一次性删除所有字符)。

有人知道如何不阻止键盘(这样我就可以使用退格键,但不能添加其他字母/符号/数字)吗?

20个回答

342
使用Swift 5和iOS 12,尝试以下实现textField(_:shouldChangeCharactersIn:replacementString:)方法,该方法是UITextFieldDelegate协议的一部分:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    guard let textFieldText = textField.text,
        let rangeOfTextToReplace = Range(range, in: textFieldText) else {
            return false
    }
    let substringToReplace = textFieldText[rangeOfTextToReplace]
    let count = textFieldText.count - substringToReplace.count + string.count
    return count <= 10
}
  • 这段代码最重要的部分是将range (NSRange) 转换为 rangeOfTextToReplace (Range<String.Index>)。请观看此视频教程以了解为什么这种转换很重要。
  • 为了使此代码正常工作,您还应该将textFieldsmartInsertDeleteType值设置为UITextSmartInsertDeleteType.no。这将防止在执行粘贴操作时插入(不需要的)额外空格的可能性。

下面的完整示例代码展示了如何在UIViewController中实现textField(_:shouldChangeCharactersIn:replacementString:)
import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var textField: UITextField! // Link this to a UITextField in Storyboard

    override func viewDidLoad() {
        super.viewDidLoad()

        textField.smartInsertDeleteType = UITextSmartInsertDeleteType.no
        textField.delegate = self
    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        guard let textFieldText = textField.text,
            let rangeOfTextToReplace = Range(range, in: textFieldText) else {
                return false
        }
        let substringToReplace = textFieldText[rangeOfTextToReplace]
        let count = textFieldText.count - substringToReplace.count + string.count
        return count <= 10
    }

}

1
你只需将这段代码放入您的视图控制器类中吗?还是我需要进行连接? - Isaac Wasserman
如果有人需要设置一些条件...你可以这样做...if (textField.isEqual(mobileNumberTextfield)) { guard let text = textField.text else { return true } let newLength = text.characters.count + string.characters.count - range.length return newLength <= limitLength; }返回真。 - Narasimha Nallamsetty
7
针对 Swift 4,text.characters.count 已经过时,请使用 text.count - Mohamed Salah

52

我是这样做的:

func checkMaxLength(textField: UITextField!, maxLength: Int) {
    if (countElements(textField.text!) > maxLength) {
        textField.deleteBackward()
    }
}

代码对我有用。 但我使用Storyboard。 在Storyboard中,我为视图控制器中的文本字段添加了一个editing changed动作。


2
countElements在Swift 2中已被更改为count,但对我来说更改后可以正常工作! - Jay
1
谢谢,现在你可以使用textField.text?.characters.count,因为countElements已经被更改了。 - Anibal R.
1
谢谢,这个更改很好用:在Swift 2中,countElements(textField.text!)是:textField.text?.characters.count - kha

42

Swift 4更新

 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
     guard let text = textField.text else { return true }
     let newLength = text.count + string.count - range.length
     return newLength <= 10
}

23
你可以扩展UITextField并添加一个@IBInspectable对象来处理它: SWIFT 5
import UIKit
private var __maxLengths = [UITextField: Int]()
extension UITextField {
    @IBInspectable var maxLength: Int {
        get {
            guard let l = __maxLengths[self] else {
                return 150 // (global default-limit. or just, Int.max)
            }
            return l
        }
        set {
            __maxLengths[self] = newValue
            addTarget(self, action: #selector(fix), for: .editingChanged)
        }
    }
    @objc func fix(textField: UITextField) {
        if let t = textField.text {
            textField.text = String(t.prefix(maxLength))
        }
    }
}

然后在属性检查器中定义它

输入图片描述

参见Swift 4原始答案


2
代码很好,很干净。但是由于某种原因,当您使用表情符号时,它会导致奇怪的编辑行为。每次尝试进行编辑时,光标都会跳到行末。 - Phontaine Judd
1
很酷的解决方案..谢谢分享!! - Frank

16

从@Martin的答案中添加更多细节。

// linked your button here
@IBAction func mobileTFChanged(sender: AnyObject) {
    checkMaxLength(sender as! UITextField, maxLength: 10)
}

// linked your button here
@IBAction func citizenTFChanged(sender: AnyObject) {
    checkMaxLength(sender as! UITextField, maxLength: 13)
}

func checkMaxLength(textField: UITextField!, maxLength: Int) {
    // swift 1.0
    //if (count(textField.text!) > maxLength) {
    //    textField.deleteBackward()
    //}
    // swift 2.0
    if (textField.text!.characters.count > maxLength) {
        textField.deleteBackward()
    }
}

1
count(textField.text!) 会出错。你必须使用 textField.text!.characters.count。 - Regis St-Gelais
1
感谢 @RegisSt-Gelais ,这已经是一个旧答案了,我现在已经更新了它。 - Sruit A.Suk

12

在 Swift 4 中

文本字段的字符限制为10个,并允许删除(使用退格键)。

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if textField ==  userNameFTF{
            let char = string.cString(using: String.Encoding.utf8)
            let isBackSpace = strcmp(char, "\\b")
            if isBackSpace == -92 {
                return true
            }
            return textField.text!.count <= 9
        }
        return true
    }

10
func checkMaxLength(textField: UITextField!, maxLength: Int) {
        if (textField.text!.characters.count > maxLength) {
            textField.deleteBackward()
        }
}

iOS 9 的小改动


8

Swift 3

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

            let nsString = NSString(string: textField.text!)
            let newText = nsString.replacingCharacters(in: range, with: string)
            return  newText.characters.count <= limitCount
    }

6

如果您想要覆盖最后一个字母:

let maxLength = 10

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

    if range.location > maxLength - 1 {
        textField.text?.removeLast()
    }

    return true
}

6

Swift 5

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    if textField == myTextFieldName {
        if range.location > 10 {
            return false
        }
    }
    return true
}

或者

func textFieldDidChangeSelection(_ textField: UITextField) {
    myTextFieldName.text = String(myTextFieldName.text!.prefix(10))
}

1
这个解决方案很容易被绕过,只需要把光标移动到文本字段的开头,然后就可以再输入另外两个字符。 - William Collishaw
第二个解决方案比第一个更好。 - Wahab Khan Jadon

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