最大长度UITextField


120

当我尝试过时如何设置可以使用swift输入到UITextField中的最大字符数?,我看到如果我全部使用10个字符,我也无法删除该字符。

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

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

Answers:


294

对于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
}
  • 该代码最重要的部分是从rangeNSRange)到rangeOfTextToReplaceRange<String.Index>)的转换。观看此视频教程以了解为何此转换很重要。
  • 为了使此代码正常工作,您还应该将textFieldsmartInsertDeleteType值设置为UITextSmartInsertDeleteType.no。这将防止在执行粘贴操作时可能会插入(多余的)多余空间。

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

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
    }

}

您是否只是将此代码放入视图控制器类中?还是我必须建立联系?
艾萨克·瓦瑟曼

如果某人需要摆一些条件,您可以这样做。if(textField .isEqual(mobileNumberTextfield)){保护let text = textField.text else {return true} let newLength = text.characters.count + string.characters.count-range.length return newLength <= limitLength; }返回true;
Narasimha Nallamsetty

5
对于Swift 4,text.characters.count已弃用text.count
Mohamed Salah's

47

我这样做是这样的:

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

该代码对我有用。但是我使用情节提要。在情节提要中,我在编辑更改时为视图控制器中的文本字段添加了一个动作。


1
countElements已更改为在Swift 2中计数,但是更改对我有用!
约翰

1
谢谢,由于countElements已更改,因此您现在可以使用textField.text?.characters.count。
阿尼巴尔·R.16年

1
韩国社交协会,它这种变化真是棒极了:countElements(的TextField.text!)在斯威夫特2:?的TextField.text .characters.count

32

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
}

15

添加来自@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

11

在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
    }

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

IOS 9的一个小改动


8

迅捷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
    }

7

您可以扩展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

5

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

let maxLength = 10

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

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

    return true
}

4

我使用张贴了一个解决方案IBInspectable,因此您可以在界面生成器中或以编程方式更改最大长度值。在这里查看


3

您可以在swift 5或swift 4中使用 类似波纹管的图像 在此处输入图片说明

  1. 在视图控制器中添加textField
  2. 连接文本到ViewController
  3. 在视图ViewController中添加代码

     class ViewController: UIViewController , UITextFieldDelegate {
    
      @IBOutlet weak var txtName: UITextField!
    
      var maxLen:Int = 8;
    
     override func viewDidLoad() {
        super.viewDidLoad()
    
        txtName.delegate = self
       }
    
     func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    
         if(textField == txtName){
            let currentText = textField.text! + string
            return currentText.count <= maxLen
         }
    
         return true;
       }
    }

您可以从GitHub下载完整源代码表单: https : //github.com/enamul95/TextFieldMaxLen


1

谨防本文中提到的UITextField的撤消错误:设置UITextField的最大字符长度

这是您迅速解决的方法

if(range.length + range.location > count(textField.text)) {
        return false;
}

如果要支持表情符号,请使用以下方法:if(range.length + range.location> count(textField.text.utf16)){返回false;}
AlexD

1
Here is my version of code. Hope it helps!

    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        let invalidCharacters = NSCharacterSet(charactersInString: "0123456789").invertedSet

        if let range = string.rangeOfCharacterFromSet(invalidCharacters, options: nil, range:Range<String.Index>(start: string.startIndex, end: string.endIndex))
        {
            return false
        }

        if (count(textField.text) > 10  && range.length == 0)
        {
            self.view.makeToast(message: "Amount entry is limited to ten digits", duration: 0.5, position: HRToastPositionCenter)
            return false
        }
        else
        {

        }

        return true
    }

1
我喜欢Toast UIView扩展程序:)
Regis St-Gelais

1

我一直在我的一个应用程序中使用此协议/扩展名,它更具可读性。我喜欢它如何识别退格键,并明确告诉您何时字符是退格键。

要考虑的一些事情:

1.无论采用哪种协议扩展,都需要指定字符数限制。通常,这将是您的ViewController,但是您可以将字符限制实现为计算属性,并返回其他内容,例如,对一个模型的字符限制。

2.您将需要在文本字段的shouldChangeCharactersInRange委托方法内调用此方法。否则,您将无法通过返回false等来阻止文本输入。

3.您可能希望允许使用退格字符。这就是为什么我添加了额外的功能来检测退格键的原因。您的shouldChangeCharacters方法可以进行检查并尽早返回“ true”,因此您始终允许退格。

protocol TextEntryCharacterLimited{
    var characterLimit:Int { get } 
}

extension TextEntryCharacterLimited{

    func charactersInTextField(textField:UITextField, willNotExceedCharacterLimitWithReplacementString string:String, range:NSRange) -> Bool{

        let startingLength = textField.text?.characters.count ?? 0
        let lengthToAdd = string.characters.count
        let lengthToReplace = range.length

        let newLength = startingLength + lengthToAdd - lengthToReplace

        return newLength <= characterLimit

    }

    func stringIsBackspaceWith(string:String, inRange range:NSRange) -> Bool{
        if range.length == 1 && string.characters.count == 0 { return true }
        return false
    }

}

如果您有兴趣,我可以在Github仓库中使用一些字符限制行为并将其放入iOS框架中。您可以实施一种协议来获得类似Twitter的字符数限制显示,向您显示超出字符数限制的距离。

Github上的CharacterLimited框架


1

由于委托是一对一关系,由于其他原因,我可能想在其他地方使用它,因此我想限制文本字段的长度,在其设置中添加以下代码:

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        setup()
    }

    required override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }

    func setup() {

        // your setup...

        setMaxLength()
    }

    let maxLength = 10

    private func setMaxLength() {
            addTarget(self, action: #selector(textfieldChanged(_:)), for: UIControlEvents.editingChanged)
        }

        @objc private func textfieldChanged(_ textField: UITextField) {
            guard let text = text else { return }
            let trimmed = text.characters.prefix(maxLength)
            self.text = String(trimmed)

        }

0

我正在使用这个;

限3个字符

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

        if let txt = textField.text {
            let currentText = txt + string
            if currentText.count > 3 {
                return false
            }
            return true
        }
        return true
    }

0

斯威夫特5

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let MAX_LENGTH = 4
        let updatedString = (textField.text! as NSString).replacingCharacters(in: range, with: string)
        return updatedString.count <= MAX_LENGTH
    }

-3

您需要检查现有字符串加上输入是否大于10。

   func textField(textField: UITextField!,shouldChangeCharactersInRange range: NSRange,    replacementString string: String!) -> Bool {
      NSUInteger newLength = textField.text.length + string.length - range.length;
      return !(newLength > 10)
   }

5
您的代码是错误的。1.您必须在Swift中使用let或var声明常量或变量(不是NSUInteger)。2. textField.text和string的类型为String。在Swift中,长度不是String的属性/方法。
Imanou Petit 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.