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


当前回答

为了使它与任何长度的字符串剪切和粘贴工作,我建议将函数更改为如下内容:

#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;
        }
    }

其他回答

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

objective - c

- (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;
}

斯威夫特

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以禁止更改。

当在文本字段的末尾输入单个字符时,范围。Location是当前字段的长度和范围。Length将为0,因为我们没有替换或删除任何东西。插入到文本字段的中间只是意味着一个不同的范围。位置,粘贴多个字符意味着字符串中有多个字符。

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

关于崩溃的“撤消”错误的说明

正如评论中提到的,UITextField有一个bug,可能导致崩溃。

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

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

Swift 3.0与复制和粘贴工作良好。

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中这样做是为了在使用数字垫时限制8个字符。

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

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

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

为了完成八月的回答,建议函数的一个可能实现(参见UITextField的委托)。

我没有测试domness代码,但我的代码不会卡住,如果用户达到了限制,它与一个新的字符串兼容,取代一个更小或等于一个。

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

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

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'

}