【问题标题】:Set the maximum character length of a UITextField设置 UITextField 的最大字符长度
【发布时间】:2010-09-30 19:20:27
【问题描述】:

当我加载 UIView 时,如何在 iPhone SDK 上设置 UITextField 中的最大字符数?

【问题讨论】:

标签: ios objective-c cocoa-touch uitextfield


【解决方案1】:

如果您限制文本计数的目的是确保文本适合其他地方的 UILabel,我会避免使用字符计数。它会因一些表情符号而崩溃(尝试截断双倍大小的表情符号可能会使您的应用程序崩溃)。这也是一些语言(如日语和中文)的问题,它们有两步输入过程,简单的计数是行不通的。

我构建了一个 UITextField 插入子类 (MPC_CharacterLimitedTextField on github)。你给它提供预期的输出标签宽度,它会处理所有语言、表情符号和粘贴问题。无论字符数如何,它都只会收集适合标签的完整字符。该项目中有一个演示,因此您可以对其进行测试以查看它是否是您所需要的。希望它会帮助任何在输出长度方面遇到与我相同问题的人。

【讨论】:

    【解决方案2】:

    您也可以使用 Swift 4 中的 NotificationCenter 来完成此操作

    NotificationCenter.default.addObserver(self, selector: #selector(self.handleTextChange(recognizer:)), name: NSNotification.Name.UITextFieldTextDidChange, object: yourTextField)
    
        @objc func handleTextChange(recognizer: NSNotification) {
                //max length is 50 charater max
                let textField = recognizer.object as! UITextField
    
                if((textField.text?.count)! > 50) {
                    let newString: String? = (textField.text as NSString?)?.substring(to: 50)
                    textField.text = newString
    
                }         
            }
    

    【讨论】:

      【解决方案3】:

      Swift 4.2 和 UITextFieldDelegate 方法

      这对我有用,并将文本字段的最大输入限制为 8 个字符。希望 NSRange 最终会更改为 Range,但现在我很高兴使用 NSString,因为从 NSRange 创建 Range 涉及到处理另一个可选项。

      func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
          let text = textField.text ?? ""
          let nsString = text as NSString
          let newText = nsString.replacingCharacters(in: range, with: string)
          return newText.count <= 8
      }
      

      【讨论】:

        【解决方案4】:

        上面给出的一些答案的问题是,例如我有一个文本字段,我必须设置输入 15 个字符的限制,然后在输入第 15 个字符后停止。但他们不允许删除。那就是删除按钮也不起作用。因为我面临同样的问题。提出了解决方案,如下所示。非常适合我

        - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
        {
         if(textField.tag==6)
         {
            if ([textField.text length]<=30)
            {
                return YES;   
            }
            else if([@"" isEqualToString:string])
            {
                textField.text=[textField.text substringToIndex:30 ];
            }
        
            return NO;
         }
         else
         {
            return YES;
         }
        }
        

        我有一个文本字段,我已将其标记设置为“6” 我已经限制了最大字符限制 = 30; 在任何情况下都可以正常工作

        【讨论】:

          【解决方案5】:
          (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
          {
              NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
          
              if ([txt_name.text length]>100)
              {
                  return NO;
              }
          
              return YES;
          }
          

          【讨论】:

            【解决方案6】:

            这限制了字符数,但还要确保您可以在字段中粘贴直到最大限制。

            - (void)textViewDidChange:(UITextView *)textView
            {
                NSString* str = [textView text];
                str = [str substringToIndex:MIN(1000,[str length])];
                [textView setText:str];
            
                if([str length]==1000) {
                    // show some label that you've reached the limit of 1000 characters
                }
            }
            

            【讨论】:

              【解决方案7】:

              除了回答原始问题并扩展 Frouo 的答案之外,这里有一些扩展来修剪空格字符串和最大长度,并利用这些字符串扩展来修剪 UITextField 到最大长度:

              // In String_Extensions.swift
              
              extension String {
              
                func trimmedString() -> String {
                  var trimmedString = self.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
                  let components = trimmedString.componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).filter { count($0) > 0 }
                  return " ".join(components)
                }
              
                func trimmedStringToMaxLength(maxLength: Int) -> String {
                  return trimmedString().substringToIndex(advance(startIndex, min(count(self), maxLength))).trimmedString()
                }
              
              }
              
              // In UITextField_Extensions.swift
              
              private var maxLengthDictionary = [UITextField : Int]()
              private var textFieldMaxLength = 20
              
              extension UITextField {
              
                @IBInspectable var maxLength: Int {
                  get {
                    if let maxLength = maxLengthDictionary[self] {
                      return maxLength
                    } else {
                      return textFieldMaxLength
                    }
                  }
                  set {
                    maxLengthDictionary[self] = newValue < textFieldMaxLength + 1 ? newValue : textFieldMaxLength
                  }
                }
              
                func trimAndLimitToMaxLength() {
                  text = text.trimmedStringToMaxLength(maxLength)
                }
              
              }
              
              let someTextField = UITextField()
              let someString = "   This   is   a   string   that   is longer than allowable for a text field.   "
              someTextField.text = someString
              someTextField.trimAndLimitToMaxLength()
              println(someTextField.text) // Prints "This is a string tha"
              let anotherTextField = UITextField()
              anotherTextField.maxLength = 5
              anotherTextField.text = someString
              anotherTextField.trimAndLimitToMaxLength()
              println(anotherTextField.text) // Prints "This"
              

              trimAndLimitToMaxLength() 可以在 UITextFieldDelegate 的textFieldDidEndEditing(_:) 中使用,以便用户可以输入或粘贴比可接受的更长的字符串,然后将其缩短而不是仅以最大长度切断输入。为此,我还将设置属性文本样式以指示超出可接受长度的任何文本部分(例如,[NSBackgroundColorAttributeName : UIColor.redColor(), NSForegroundColorAttributeName : UIColor.whiteColor(), NSStrikethroughStyleAttributeName : NSNumber(int: 1)]

              【讨论】:

              • 全局字典不会通过持有对所有文本视图的引用(直到根目录都引用超级视图)来创建内存泄漏
              【解决方案8】:

              我们可以像这样设置文本字段的范围..

              -(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range  replacementString:(NSString *)string
              {
                   int setrange = 20;
                   return !([textField.text length]>setrange && [string length] > range.length);
              }
              

              【讨论】:

                【解决方案9】:

                对于 Swift 2.1+

                func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
                
                    if (range.length + range.location > textField.text!.characters.count )
                    {
                        return false;
                    }
                
                    let newLength = textField.text!.characters.count + string.characters.count - range.length
                    return newLength <= 25
                }
                

                希望对你有帮助

                【讨论】:

                  【解决方案10】:

                  我想补充@sickp 给出的答案。

                  他的Swift 代码中存在一个问题,该问题出现在任何多字节文本(例如表情符号)中。 NSRangeSwift 中的 String 不兼容,因此委托类将它们结合起来令人沮丧。诀窍是将String 对象转换为NSString 根据@sickp 所写的内容,正确的解决方案实际上是这样的:

                  func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
                  
                      let currentText = (textField.text as NSString?) ?? NSString()
                      let currentCharacterCount = currentText.length
                      if range.length + range.location > currentCharacterCount {
                          return false
                      }
                      let newLength = currentText.replacingCharacters(in: range, with: string).characters.count
                      return newLength <= 25
                  }
                  

                  【讨论】:

                    【解决方案11】:

                    适用于 Swift 3.1 或更高版本

                    首先添加协议UITextFieldDelegate

                    喜欢:-

                    class PinCodeViewController: UIViewController, UITextFieldDelegate { 
                    .....
                    .....
                    .....
                    
                    }
                    

                    之后创建你的 UITextField 并设置委托

                    完整的经验:-

                    import UIKit
                    
                    class PinCodeViewController: UIViewController, UITextFieldDelegate {
                    
                    let pinCodetextField: UITextField = {
                        let tf = UITextField()
                        tf.placeholder = "please enter your pincode"
                        tf.font = UIFont.systemFont(ofSize: 15)
                        tf.borderStyle = UITextBorderStyle.roundedRect
                        tf.autocorrectionType = UITextAutocorrectionType.no
                        tf.keyboardType = UIKeyboardType.numberPad
                        tf.clearButtonMode = UITextFieldViewMode.whileEditing;
                        tf.contentVerticalAlignment = UIControlContentVerticalAlignment.center
                     return tf
                      }()
                    
                    
                     override func viewDidLoad() {
                       super.viewDidLoad()
                       view.addSubview(pinCodetextField)
                        //----- setup your textfield anchor or position where you want to show it----- 
                    
                    
                        // after that 
                    pinCodetextField.delegate = self // setting the delegate
                    
                     }
                    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
                        return !(textField.text?.characters.count == 6 && string != "")
                         } // this is return the maximum characters in textfield 
                        }
                    

                    【讨论】:

                      【解决方案12】:

                      在 Swift 5.2 中工作

                       class AngListVC: UIViewController, UITextFieldDelegate {
                      
                          @IBOutlet weak var angTextField: UITextField!
                      
                          override func viewDidLoad() {
                              super.viewDidLoad()
                              angTextField.delegate = self
                              angTextField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
                            
                          }
                      
                         func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
                                 let userText =  angTextField.text ?? ""
                                 var newText = ""
                                 if range.length > 0 {
                                     let txt = NSString(string: userText)
                                     if txt.length > 0 {
                                         newText = txt.replacingCharacters(in: range, with: "")
                                     }
                                 } else {
                                     newText = userText + ""
                                 }
                                 return newText.count <= 3
                             }
                      
                      @objc func textFieldDidChange(_ textField: UITextField) {
                              print("textFieldDidChange")
                         }
                      

                      【讨论】:

                        【解决方案13】:

                        对于 Swift 5

                        添加这个 UITextfield 的扩展,然后选择一个文本域并检查属性检查器

                        private var __maxLengths = [UITextField: Int]()
                        
                        extension UITextField {
                            @IBInspectable var maxLength: Int {
                                get {
                                    guard let l = __maxLengths[self] else {
                                       return 150 // (default int limit)
                                    }
                                    return l
                                }
                                set {
                                    __maxLengths[self] = newValue
                                    addTarget(self, action: #selector(setMaxLength), for: .editingChanged)
                                }
                            }
                        
                            @objc func setMaxLength(textField: UITextField) {
                                let t = textField.text
                                textField.text = t?.prefix(maxLength).description
                            }
                        }
                        

                        【讨论】:

                          【解决方案14】:
                          -(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
                              if (textField.text.length >= 50) {
                                  return NO;
                              }
                              return YES;
                          }
                          

                          【讨论】:

                          • 这不会让您输入超过或等于 50 个字符。
                          【解决方案15】:

                          Swift 4.2+

                          通过实现UITextFieldDelegate方法

                          1. 视图控制器:

                            class MyViewController: UIViewController {
                            
                                let MAX_LENGTH = 256
                            
                                @IBOutlet weak var myTextField: UITextField!
                            
                                override viewDidLoad() {
                                    self.myTextField.delegate = self
                                }
                            }
                            
                          2. 代表:

                            extension MyViewController: UITextFieldDelegate {
                            
                                func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
                                    let userText =  textView.text ?? ""
                                    var newText = ""
                                    if range.length > 0 {
                                        let txt = NSString(string: userText)
                                        if txt.length > 0 {
                                            newText = txt.replacingCharacters(in: range, with: text)
                                        }
                                    } else {
                                        newText = userText + text
                                    }
                                    return newText.count <= MAX_LENGTH
                                }
                            
                            }
                            

                          【讨论】:

                          • 这不会编译
                          • @Lucas 哦,真的吗?这段代码来自真实的项目。你应该再试一次。
                          【解决方案16】:

                          我发现这个快速简单

                          - (IBAction)backgroundClick:(id)sender {
                              if (mytext.length <= 7) {
                                  [mytext resignFirstResponder];
                              } else {
                                  UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Too Big" 
                                                                                  message:@"Please Shorten Name"
                                                                                 delegate:nil 
                                                                        cancelButtonTitle:@"Cancel"
                                                                        otherButtonTitles:nil];
                                  [alert show];
                                  [alert release];
                              }
                          }
                          

                          【讨论】:

                          • Apple 不鼓励这样使用UIAlertViews。您应该为重要消息保留警报,并且只允许输入,就像在接受的答案中一样。
                          • 不是正确的方法! --- 插入完整字符串后,用户将了解输入大小!
                          猜你喜欢
                          • 2018-03-12
                          • 2011-02-01
                          • 2015-09-30
                          • 1970-01-01
                          • 1970-01-01
                          • 2014-10-03
                          • 2012-04-27
                          相关资源
                          最近更新 更多