关于ios:设置UITextField的最大字符长度

Set the maximum character length of a UITextField

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


虽然UITextField类没有max length属性,但通过设置文本字段的delegate并实现以下委托方法来获得此功能相对简单:

Objective-C的

1
2
3
4
5
6
7
8
9
10
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    // Prevent crashing undo bug – see note below.
    if(range.length + range.location > textField.text.length)
    {
        return NO;
    }

    NSUInteger newLength = [textField.text length] + [string length] - range.length;
    return newLength <= 25;
}

迅速

1
2
3
4
5
6
7
8
9
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    let currentCharacterCount = textField.text?.count ?? 0
    if range.length + range.location > currentCharacterCount {
        return false
    }
    let newLength = currentCharacterCount + string.count - range.length
    return newLength <= 25
}

在文本字段更改之前,UITextField会询问委托是否应更改指定的文本。此时文本字段没有改变,所以我们抓住它的当前长度和我们插入的字符串长度(通过粘贴复制的文本或使用键盘键入单个字符),减去范围长度。如果此值太长(在此示例中超过25个字符),则返回NO以禁止更改。

在文本字段末尾键入单个字符时,range.location将是当前字段的长度,range.length将为0,因为我们不替换/删除任何内容。插入文本字段的中间只是意味着不同的range.location,并且粘贴多个字符只意味着string中包含多个字符。

删除单个字符或剪切多个字符由range指定,长度为非零,空字符串。替换只是一个非空字符串的范围删除。

关于崩溃"撤消"错误的说明

正如评论中所提到的,UITextField存在一个可能导致崩溃的错误。

如果您粘贴到该字段,但验证实现阻止了粘贴,则粘贴操作仍会记录在应用程序的撤消缓冲区中。如果然后触发撤消(通过摇动设备并确认撤消),UITextField将尝试用空字符串替换它认为粘贴的字符串。这会崩溃,因为它从未真正将字符串粘贴到自身。它将尝试替换不存在的字符串的一部分。

幸运的是,你可以保护UITextField不会像这样自杀。您只需要确保它建议替换的范围确实存在于其当前字符串中。这是上面的初步健全检查。

swift 3.0,复制和粘贴工作正常。

1
2
3
4
5
6
7
8
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        let str = (textView.text + text)
        if str.characters.count <= 10 {
            return true
        }
        textView.text = str.substring(to: str.index(str.startIndex, offsetBy: 10))
        return false
    }

希望它对你有所帮助。


谢谢八月! (POST)

这是我最终使用的代码:

1
2
3
4
5
6
7
8
9
10
11
#define MAX_LENGTH 20

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if (textField.text.length >= MAX_LENGTH && range.length == 0)
    {
        return NO; // return NO to not change text
    }
    else
    {return YES;}
}


斯威夫特4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import UIKit

private var kAssociationKeyMaxLength: Int = 0

extension UITextField {

    @IBInspectable var maxLength: Int {
        get {
            if let length = objc_getAssociatedObject(self, &kAssociationKeyMaxLength) as? Int {
                return length
            } else {
                return Int.max
            }
        }
        set {
            objc_setAssociatedObject(self, &kAssociationKeyMaxLength, newValue, .OBJC_ASSOCIATION_RETAIN)
            addTarget(self, action: #selector(checkMaxLength), for: .editingChanged)
        }
    }

    @objc func checkMaxLength(textField: UITextField) {
        guard let prospectiveText = self.text,
            prospectiveText.count > maxLength
            else {
                return
        }

        let selection = selectedTextRange

        let indexEndOfText = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
        let substring = prospectiveText[..<indexEndOfText]
        text = String(substring)

        selectedTextRange = selection
    }
}

编辑:内存泄漏问题已修复。

enter image description here


要完成8月份答案,可以实现所提议的函数(请参阅UITextField的委托)。

我没有测试domness代码,但是如果用户达到了限制,我不会卡住,并且它与替换较小或相等的新字符串兼容。

1
2
3
4
5
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    //limit the size :
    int limit = 20;
    return !([textField.text length]>limit && [string length] > range.length);
}


你不能直接这样做 - UITextField没有maxLength属性,但你可以设置UITextField's委托,然后使用:

1
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string


通常,您有多个具有不同长度的输入字段。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    int allowedLength;
    switch(textField.tag) {
        case 1:
            allowedLength = MAXLENGTHNAME;      // triggered for input fields with tag = 1
            break;
        case 2:
            allowedLength = MAXLENGTHADDRESS;   // triggered for input fields with tag = 2
            break;
        default:
            allowedLength = MAXLENGTHDEFAULT;   // length default when no tag (=0) value =255
            break;
    }

    if (textField.text.length >= allowedLength && range.length == 0) {
        return NO; // Change not allowed
    } else {
        return YES; // Change allowed
    }
}

最好的方法是设置文本更改通知。在您的视图控制器方法的-awakeFromNib中,您需要:

1
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(limitTextField:) name:@"UITextFieldTextDidChangeNotification" object:myTextField];

然后在同一个类中添加:

1
2
3
4
5
6
- (void)limitTextField:(NSNotification *)note {
    int limit = 20;
    if ([[myTextField stringValue] length] > limit) {
        [myTextField setStringValue:[[myTextField stringValue] substringToIndex:limit]];
    }
}

然后将插座myTextField链接到UITextField,并且在达到限制后不会再添加任何字符。请务必将此添加到您的dealloc方法:

1
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"UITextFieldTextDidChangeNotification" object:myTextField];


这应该足以解决问题(用你想要的限制替换4)。只需确保在IB中添加委托。

1
2
3
4
5
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
     NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
     return (newString.length<=4);
}

我创建了这个UITextFieldLimit子类:

  • 支持多个文本字段
  • 设置文本长度限制
  • 粘贴预防
  • 在文本字段内显示左侧字符的标签,在停止编辑时隐藏。
  • 没有人物离开时动摇动画。

从此GitHub存储库中获取UITextFieldLimit.hUITextFieldLimit.m

https://github.com/JonathanGurebo/UITextFieldLimit

并开始测试!

标记您的故事板创建的UITextField并使用Identity Inspector将其链接到我的子类:

Identity Inspector

然后,您可以将其链接到IBOutlet并设置限制(默认值为10)。

您的ViewController.h文件应包含:(如果您不想修改设置,如限制)

1
2
3
4
5
#import"UITextFieldLimit.h"

/.../

@property (weak, nonatomic) IBOutlet UITextFieldLimit *textFieldLimit; // <--Your IBOutlet

您的ViewController.m文件应@synthesize textFieldLimit

在ViewController.m文件中设置文本长度限制:

1
2
3
4
5
6
7
- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

    [textFieldLimit setLimit:25];// <-- and you won't be able to put more than 25 characters in the TextField.
}

希望全班同学帮助你。祝好运!


我模拟了即将发生的实际字符串替换,以计算未来字符串的长度:

1
2
3
4
5
6
7
8
9
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {

    NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];

    if([newString length] > maxLength)
       return NO;

    return YES;
}

Swift 3版
// *****这不适用于Swift 2.x! // *****

首先创建一个新的Swift文件:TextFieldMaxLength.swift,
然后添加以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import UIKit

private var maxLengths = [UITextField: Int]()

extension UITextField {

   @IBInspectable var maxLength: Int {

      get {

          guard let length = maxLengths[self]
             else {
                return Int.max
      }
      return length
   }
   set {
      maxLengths[self] = newValue
      addTarget(
         self,
         action: #selector(limitLength),
         for: UIControlEvents.editingChanged
      )
   }
}
func limitLength(textField: UITextField) {
    guard let prospectiveText = textField.text,
        prospectiveText.characters.count > maxLength
    else {
        return
    }

   let selection = selectedTextRange
   let maxCharIndex = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
   text = prospectiveText.substring(to: maxCharIndex)
   selectedTextRange = selection
   }
}

然后,当您选择任何TextField时,您将在Storyboard中看到一个新字段(Max Length)

如果您还有更多问题,请查看以下链接:http://www.globalnerdy.com/2016/05/18/ios-programming-trick-how-to-use-xcode-to-set-a-text-fields - 最大长度视觉工作室风格/


使用"界面"构建器,您可以在任何功能中链接并获取"编辑已更改"的事件。
现在你可以检查长度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- (IBAction)onValueChange:(id)sender
{
    NSString *text = nil;
    int MAX_LENGTH = 20;
    switch ([sender tag] )
    {
        case 1:
        {
            text = myEditField.text;
            if (MAX_LENGTH < [text length]) {
                myEditField.text = [text substringToIndex:MAX_LENGTH];
            }
        }
            break;
        default:
            break;
    }

}

以下代码类似于sickp的答案,但处理正确的复制粘贴操作。如果您尝试粘贴长度超过限制的文本,以下代码将截断文本以适应限制,而不是完全拒绝粘贴操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    static const NSUInteger limit = 70; // we limit to 70 characters
    NSUInteger allowedLength = limit - [textField.text length] + range.length;
    if (string.length > allowedLength) {
        if (string.length > 1) {
            // get at least the part of the new string that fits
            NSString *limitedString = [string substringToIndex:allowedLength];
            NSMutableString *newString = [textField.text mutableCopy];
            [newString replaceCharactersInRange:range withString:limitedString];
            textField.text = newString;
        }
        return NO;
    } else {
        return YES;
    }
}

在Swift中设置最大长度的通用解决方案。
通过IBInspectable,您可以在Xcode Attribute Inspector中添加新属性。enter image description here

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import UIKit
private var maxLengths = [UITextField: Int]()
extension UITextField {

    @IBInspectable var maxLength: Int {
        get {
            guard let length = maxLengths[self]
            else {
                return Int.max
            }
            return length
        }
        set {
            maxLengths[self] = newValue
            addTarget(
                self,
                action: Selector("limitLength:"),
                forControlEvents: UIControlEvents.EditingChanged
            )
        }
    }

    func limitLength(textField: UITextField) {
        guard let prospectiveText = textField.text
            where prospectiveText.characters.count > maxLength else {
                return
        }
        let selection = selectedTextRange
        text = prospectiveText.substringWithRange(
            Range<String.Index>(prospectiveText.startIndex ..< prospectiveText.startIndex.advancedBy(maxLength))
        )
        selectedTextRange = selection
    }

}


为了使它能够剪切和粘贴任何长度的字符串,我建议将函数更改为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#define MAX_LENGTH 20

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
    {
        NSInteger insertDelta = string.length - range.length;

        if (textField.text.length + insertDelta > MAX_LENGTH)
        {
           return NO; // the new string would be longer than MAX_LENGTH
        }
        else {
            return YES;
        }
    }

swift 3.0

粘贴字符串超过字符限制时,此代码工作正常。

1
2
3
4
5
6
7
8
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        let str = (textView.text + text)
        if str.characters.count <= 10 {
            return true
        }
        textView.text = str.substring(to: str.index(str.startIndex, offsetBy: 10))
        return false
    }

谢谢你的投票。 :)


Swift 2.0 +

首先为此过程创建一个类。让我们称之为StringValidator.swift。

然后只需在其中粘贴以下代码即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import Foundation

extension String {

func containsCharactersIn(matchCharacters: String) -> Bool {
let characterSet = NSCharacterSet(charactersInString: matchCharacters)
return self.rangeOfCharacterFromSet(characterSet) != nil
}

func containsOnlyCharactersIn(matchCharacters: String) -> Bool {
let disallowedCharacterSet = NSCharacterSet(charactersInString: matchCharacters).invertedSet
return self.rangeOfCharacterFromSet(disallowedCharacterSet) == nil
}


func doesNotContainCharactersIn(matchCharacters: String) -> Bool {
let characterSet = NSCharacterSet(charactersInString: matchCharacters)
return self.rangeOfCharacterFromSet(characterSet) == nil
}

func isNumeric() -> Bool
{
let scanner = NSScanner(string: self)
scanner.locale = NSLocale.currentLocale()

return scanner.scanDecimal(nil) && scanner.atEnd
}

}

现在保存班级......

用法..

现在转到你的viewController.swift类,并将你的textfield的出口作为..

1
2
@IBOutlet weak var contactEntryTxtFld: UITextField! //First textfield
@IBOutlet weak var contactEntryTxtFld2: UITextField!   //Second textfield

现在转到textfield的shouldChangeCharactersInRange方法并使用如下所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    if string.characters.count == 0 {
        return true
    }
    let latestText = textField.text ??""
    let checkAbleText = (latestText as NSString).stringByReplacingCharactersInRange(range, withString: string)


    switch textField {

    case contactEntryTxtFld:
        return checkAbleText.containsOnlyCharactersIn("0123456789") && prospectiveText.characters.count <= 5

    case contactEntryTxtFld2:
        return checkAbleText.containsOnlyCharactersIn("0123456789") && prospectiveText.characters.count <= 5

    default:
        return true
    }

}

不要忘记设置文本字段的委托协议/方法。

让我解释一下......我正在使用我在另一个类中编写的字符串的简单扩展过程。现在我只是通过添加检查和最大值来从我需要它的另一个类调用这些扩展方法。

特征...

  • 它将设置特定文本字段的最大限制。
  • 它将设置特定文本字段的已接受键的类型。
  • 类型...

    containsOnlyCharactersIn //仅接受字符。

    containsCharactersIn //接受字符组合

    doesNotContainsCharactersIn //不接受字符

    希望这有助于....
    谢谢..


    使用以下扩展名设置UITextFieldUITextView的最大字符长度。

    Swift 4.0

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
        private var kAssociationKeyMaxLength: Int = 0
        private var kAssociationKeyMaxLengthTextView: Int = 0
        extension UITextField {


            @IBInspectable var maxLength: Int {
                get {
                    if let length = objc_getAssociatedObject(self, &kAssociationKeyMaxLength) as? Int {
                        return length
                    } else {
                        return Int.max
                    }
                }
                set {
                    objc_setAssociatedObject(self, &kAssociationKeyMaxLength, newValue, .OBJC_ASSOCIATION_RETAIN)
                    addTarget(self, action: #selector(checkMaxLength), for: .editingChanged)
                }
            }

            @objc func checkMaxLength(textField: UITextField) {
                guard let prospectiveText = self.text,
                    prospectiveText.count > maxLength
                    else {
                        return
                }

                let selection = selectedTextRange

                let indexEndOfText = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
                let substring = prospectiveText[..<indexEndOfText]
                text = String(substring)

                selectedTextRange = selection
            }
        }

        extension UITextView:UITextViewDelegate {


        @IBInspectable var maxLength: Int {
            get {
                if let length = objc_getAssociatedObject(self, &kAssociationKeyMaxLengthTextView) as? Int {
                    return length
                } else {
                    return Int.max
                }
            }
            set {
                self.delegate = self

                objc_setAssociatedObject(self, &kAssociationKeyMaxLengthTextView, newValue, .OBJC_ASSOCIATION_RETAIN)
            }
        }

        public func textViewDidChange(_ textView: UITextView) {
            checkMaxLength(textField: self)
        }
        @objc func checkMaxLength(textField: UITextView) {
            guard let prospectiveText = self.text,
                prospectiveText.count > maxLength
                else {
                    return
            }

            let selection = selectedTextRange

            let indexEndOfText = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
            let substring = prospectiveText[..<indexEndOfText]
            text = String(substring)

            selectedTextRange = selection
        }
    }

    您可以在下面设置限制。

    enter image description here


    斯威夫特4

    1
    2
    3
    4
    5
    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
    }


    我基于@Frouo给出了补充答案。我认为他的回答是最美好的方式。因为它是我们可以重复使用的通用控件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    private var kAssociationKeyMaxLength: Int = 0

    extension UITextField {

        @IBInspectable var maxLength: Int {
            get {
                if let length = objc_getAssociatedObject(self, &kAssociationKeyMaxLength) as? Int {
                    return length
                } else {
                    return Int.max
                }
            }
            set {
                objc_setAssociatedObject(self, &kAssociationKeyMaxLength, newValue, .OBJC_ASSOCIATION_RETAIN)
                self.addTarget(self, action: #selector(checkMaxLength), for: .editingChanged)
            }
        }

        func checkMaxLength(textField: UITextField) {

            guard !self.isInputMethod(), let prospectiveText = self.text,
                prospectiveText.count > maxLength
                else {
                    return
            }

            let selection = selectedTextRange
            let maxCharIndex = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
            text = prospectiveText.substring(to: maxCharIndex)
            selectedTextRange = selection
        }

        //The method is used to cancel the check when use Chinese Pinyin input method.
        //Becuase the alphabet also appears in the textfield when inputting, we should cancel the check.
        func isInputMethod() -> Bool {
            if let positionRange = self.markedTextRange {
                if let _ = self.position(from: positionRange.start, offset: 0) {
                    return true
                }
            }
            return false
        }

    }

    这是在UITextField上处理最大长度的正确方法,它允许返回键退出作为第一响应者的文本字段,并在用户达到限制时让用户退格

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    int MAX_LENGHT = 5;
        if([string isEqualToString:@"
    "
    ])
        {
            [textField resignFirstResponder];
            return FALSE;
        }
        else if(textField.text.length > MAX_LENGHT-1)
        {
            if([string isEqualToString:@""] && range.length == 1)
            {
                return TRUE;
            }
            else
            {
                return FALSE;
            }
        }
        else
        {
            return TRUE;
        }
    }

    对于Xamarin:

    1
    2
    3
    4
    5
    YourTextField.ShouldChangeCharacters =
    delegate(UITextField textField, NSRange range, string replacementString)
            {
                return (range.Location + replacementString.Length) <= 4; // MaxLength == 4
            };

    Swift 4.2和UITextFieldDelegate方法

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

    1
    2
    3
    4
    5
    6
    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
    }

    这个简单的方法怎么样? 它对我来说很好。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    extension UITextField {

        func  charactersLimit(to:Int) {

            if (self.text!.count > to) {
                self.deleteBackward()
            }
        }
    }

    然后:

    1
    someTextField.charactersLimit(to:16)


    您也可以使用Swift 4中的NotificationCenter执行此操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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

                }        
            }

    其他答案不处理用户可以从剪贴板粘贴长字符串的情况。如果我粘贴一个长字符串,它应该被截断但显示。
    在你的代表中使用它:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    static const NSUInteger maxNoOfCharacters = 5;

    -(IBAction)textdidChange:(UITextField * )textField
    {
    NSString * text = textField.text;

    if(text.length > maxNoOfCharacters)
    {
        text = [text substringWithRange:NSMakeRange(0, maxNoOfCharacters)];
        textField.text = text;
    }

    // use 'text'

    }

    现在你想要多少个字符给出值

    1
    2
    3
    4
     - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range   replacementString:(NSString *)string {
         NSUInteger newLength = [textField.text length] + [string length] - range.length;
         return (newLength > 25) ? NO : YES;
      }

    我已经实现了一个UITextField扩展来为它添加一个maxLength属性。

    它基于Xcode 6 IBInspectables,因此您可以在"接口"构建器上设置maxLength限制。

    这是实施:

    UITextField+MaxLength.h

    1
    2
    3
    4
    5
    6
    #import <UIKit/UIKit.h>

    @interface UITextField_MaxLength : UITextField<UITextFieldDelegate>

    @property (nonatomic)IBInspectable int textMaxLength;
    @end

    UITextField+MaxLength.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    #import"UITextField+MaxLength.h"

    @interface UITextField_MaxLength()

    @property (nonatomic, assign) id <UITextFieldDelegate> superDelegate;

    @end

    @implementation UITextField_MaxLength

    - (BOOL)textField:(UITextField *) textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {

        //validate the length, only if it's set to a non zero value
        if (self.textMaxLength>0) {
            if(range.length + range.location > textField.text.length)
                return NO;

            if (textField.text.length+string.length - range.length>self.textMaxLength) {
                return NO;
            }
        }

        //if length validation was passed, query the super class to see if the delegate method is implemented there
        if (self.superDelegate && [self.superDelegate respondsToSelector:@selector(textField:shouldChangeCharactersInRange:replacementString:)]) {
            return [self.superDelegate textField:textField shouldChangeCharactersInRange:range replacementString:string];
        }
        else{
            //if the super class does not implement the delegate method, simply return YES as the length validation was passed
            return YES;
        }
    }

    - (void)setDelegate:(id<UITextFieldDelegate>)delegate {
        if (delegate == self)
            return;
        self.superDelegate = delegate;
        [super setDelegate:self];
    }

    //forward all non overriden delegate methods
    - (id)forwardingTargetForSelector:(SEL)aSelector {
        if ([self.superDelegate  respondsToSelector:aSelector])
            return self.superDelegate;

        return [super forwardingTargetForSelector:aSelector];
    }

    - (BOOL)respondsToSelector:(SEL)aSelector {
        if ([self.superDelegate respondsToSelector:aSelector])
            return YES;

        return [super respondsToSelector:aSelector];
    }
    @end

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

    我构建了一个UITextField drop-in子类(github上的MPC_CharacterLimitedTextField)。您为它提供了预期的输出标签宽度,它将处理所有语言,表情符号和粘贴问题。无论字符数是多少,它都只会收集适合标签的多个完整字符。项目中有一个演示,所以你可以测试它,看看它是否是你需要的。希望它能帮助任何与输出长度问题相同的人。


    把它归结为1行代码:)

    将文本视图的委托设置为"self",然后在.h中添加,并在.m中添加以下代码....您可以将数字"7"调整为您想要的最大字符数到是。

    1
    2
    3
    -(BOOL)textView:(UITextView *)a shouldChangeTextInRange:(NSRange)b replacementText:(NSString *)c {
        return ((a.text.length+c.length<=7)+(c.length<1)+(b.length>=c.length)>0);
    }

    此代码用于键入新字符,删除字符,选择字符然后键入或删除,选择字符和剪切,粘贴,以及选择字符和粘贴。

    完成!

    或者,使用位操作编写此代码的另一种很酷的方法是

    1
    2
    3
    -(BOOL)textView:(UITextView *)a shouldChangeTextInRange:(NSRange)b replacementText:(NSString *)c {
        return 0^((a.text.length+c.length<=7)+(c.length<1)+(b.length>=c.length));
    }

    当我使用数字键盘时,我在Swift中做了8个字符的限制。

    1
    2
    3
    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        return !(textField.text?.characters.count == MAX_LENGTH && string !="")
    }

    我必须测试字符串!="以允许删除按钮在数字键盘上工作,否则它将不允许在文本字段达到其最大值后删除字符。


    我已经开源了一个UITextField子类STATextField,它通过其maxCharacterLength属性提供了这个功能(以及更多)。


    在此处使用此代码RESTRICTED_LENGTH是您要为textfield限制的长度。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
       - (BOOL)textField:(UITextField *)textField     shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
    {
        if (textField == nameTF) {
        int limit = RESTRICTED_LENGTH - 1;
        return !([textField.text length]>limit && [string length] > range.length);
        }
       else
       {
        return YES;
       }

    return NO;

    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    (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;
    }


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

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    - (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
        }
    }

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

    他的Swift代码中存在任何多字节文本(例如emojis)的问题。 Swift中的NSRangeString不兼容,因此委托类将它们组合起来令人沮丧。诀窍就是将String对象转换为NSString正确的解决方案,基于@sickp写的,实际上是这样的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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
    }

    对于Swift 3.1或更高版本

    首先添加协议UITextFieldDelegate

    喜欢:-

    1
    2
    3
    4
    5
    6
    class PinCodeViewController: UIViewController, UITextFieldDelegate {
    .....
    .....
    .....

    }

    之后,创建您的UITextField并设置委托

    完成Exp: -

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    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
        }

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    - (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;
    在每种情况下都能正常工作


    稍微回答原始问题,并扩展Frouo的答案,这里是修剪一个空格字符串和最大长度的扩展,并利用这些字符串扩展将UITextField修剪为最大长度:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    // 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)]


    适用于Swift 2.1+

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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
    }

    希望能帮助到你


    Swift 4.2+

    通过实现UITextFieldDelegate方法

  • 视图控制器:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class MyViewController: UIViewController {

        let MAX_LENGTH = 256

        @IBOutlet weak var myTextField: UITextField!

        override viewDidLoad() {
            self.myTextField.delegate = self
        }
    }
  • 代表:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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
        }

    }

  • 1
    2
    3
    4
    5
    6
    -(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
        if (textField.text.length >= 50) {
            return NO;
        }
        return YES;
    }


    我发现这很简单

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    - (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];
        }
    }