【问题标题】:Max length UITextField最大长度 UITextField
【发布时间】:2014-10-03 02:36:24
【问题描述】:

当我尝试How to you set the maximum number of characters that can be entered into a UITextField using swift? 时,我发现如果我使用所有 10 个字符,我也无法删除该字符。

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

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

【问题讨论】:

    标签: ios swift uitextfield character max


    【解决方案1】:

    在 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&lt;String.Index&gt;) 的转换。请参阅此video tutorial,了解为什么这种转换很重要。
    • 要使此代码正常工作,您还应该将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
        }
    
    }
    

    【讨论】:

    • 你只是把这段代码放在你的视图控制器类中吗?还是我必须建立联系?
    • 如果有人需要设置一些条件......你可以这样做...... if (textField .isEqual(mobileNumberTextfield)) { guard let text = textField.text else { return true } let newLength = text.characters.count + string.characters.count - range.length return newLength
    • 对于 Swift 4,text.characters.count 已弃用,使用 text.count
    【解决方案2】:

    我是这样做的:

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

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

    【讨论】:

    • countElements 已更改为在 Swift 2 中计数,但更改对我有用!
    • 谢谢,您现在可以使用 textField.text?.characters.count,因为 countElements 已更改。
    • Tks,这个改动效果很好:Swift 2 中的 countElements(textField.text!) 是:textField.text?.characters.count
    【解决方案3】:

    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
    }
    

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 漂亮、干净的代码。但是由于某种原因,当您使用表情符号时,这会导致奇怪的编辑行为。每次尝试编辑时,光标都会跳到行尾。
      • 很酷的解决方案 ..thanx 分享!!
      【解决方案5】:

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

      【讨论】:

      • count(textField.text!) 给出错误。您必须使用 textField.text!.characters.count
      • 谢谢@RegisSt-Gelais,这已经是一个旧答案了,我现在更新了
      【解决方案6】:

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

      【讨论】:

        【解决方案7】:
        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
              }
          

          【讨论】:

            【解决方案9】:

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

            let maxLength = 10
            
            func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
            
                if range.location > maxLength - 1 {
                    textField.text?.removeLast()
                }
            
                return true
            }
            

            【讨论】:

              【解决方案10】:

              我使用IBInspectable 发布了一个解决方案,因此您可以在界面生成器中或以编程方式更改最大长度值。 Check it out here

              【讨论】:

                【解决方案11】:

                您可以在 swift 5 或 swift 4 中使用图片如下所示

                1. 在视图控制器中添加文本字段
                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

                【讨论】:

                  【解决方案12】:

                  斯威夫特 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
                      }
                  

                  【讨论】:

                    【解决方案13】:

                    斯威夫特 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))
                    }
                    

                    【讨论】:

                    • 通过将光标移动到文本字段的开头可以轻松绕过此解决方案。然后你可以再输入两个字符。
                    【解决方案14】:

                    注意这篇文章中提到的 UITextField 的撤消错误:Set the maximum character length of a UITextField

                    这里是你如何快速修复它

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

                    【讨论】:

                    • 如果要支持表情符号等使用: if (range.length + range.location > count(textField.text.utf16)){ return false; }
                    【解决方案15】:
                    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
                        }
                    

                    【讨论】:

                    • 我喜欢 Toast UIView 扩展 :)
                    【解决方案16】:

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

                    需要考虑的一些事项:

                    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 的字符限制显示,显示您超出字符限制的程度。

                    CharacterLimited Framework on Github

                    【讨论】:

                      【解决方案17】:

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

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

                      【讨论】:

                        【解决方案18】:

                        我正在使用这个;

                        限制为 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
                            }
                        

                        【讨论】:

                          【解决方案19】:

                          这是我的简单答案,在 Swift 5.0 中使用 iOS 14+ 和 Xcode 12+...

                          viewDidLoad() 中添加以下选择器:

                          override func viewDidLoad() {
                              // Add a target for myTextField, pointing to .editingDidChange
                              myTextField.addTarget(self, action: #selector(myTextFieldDidChange(_:)), for: .editingChanged)
                          }
                          

                          在你的课堂上,你还可以添加一个可选的字符限制:

                          // Add an optional character limit
                          let characterLimit = 100
                          

                          然后在你的课堂上,添加这个函数:

                          @objc func myTextFieldDidChange(_ textField: UITextField) {
                              textField.text = String(textField.text!.prefix(self.characterLimit))
                          }
                          

                          这将在您键入时限制您的字符,在您将文本复制+粘贴到文本字段时。

                          【讨论】:

                            【解决方案20】:

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

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

                            【讨论】:

                            • 您的代码错误。 1. 你必须在 Swift(不是 NSUInteger)中用 let 或 var 声明你的常量或变量。 2. textField.text 和 string 是 String 类型。长度不是 Swift 中 String 的属性/方法。
                            猜你喜欢
                            • 2011-02-01
                            • 2010-09-30
                            • 1970-01-01
                            • 2018-03-12
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多