UITextFiled,UITextView限制文本输入长度

很多时候需要简单的限制一下文本输入框的文本长度.写多了类似的代码之后,想把它封装一下一劳永逸.封装后将一行代码搞定文本输入长度限制.
封装一个UITextField的分类:

@interface UITextField (XQHelper)

//限制UITextField的输入字数.0表示无限制.
@property (nonatomic, assign) NSInteger xq_limitTextLength;

@end
@implementation UITextField (XQHelper)

- (NSInteger)xq_limitTextLength
{
    NSNumber *limit = objc_getAssociatedObject(self, @selector(xq_limitTextLength));
    return limit.integerValue;
}

- (void)setXq_limitTextLength:(NSInteger)xq_limitTextLength
{
    objc_setAssociatedObject(self, @selector(xq_limitTextLength), @(xq_limitTextLength), OBJC_ASSOCIATION_ASSIGN);
    
    [self removeTarget:self action:@selector(textFieldTextDidChanged:) forControlEvents:UIControlEventEditingChanged];
    [self addTarget:self action:@selector(textFieldTextDidChanged:) forControlEvents:UIControlEventEditingChanged];
}

- (void)textFieldTextDidChanged:(UITextField *)textField
{
    if (self.xq_limitTextLength <= 0) {
        return;
    }
    
    NSString *contentText = textField.text;
    //防止系统中文键盘输入bug
    // 获取高亮内容的范围
    UITextRange *selectedRange = [textField markedTextRange];
    // 获取高亮内容的长度
    NSInteger markedTextLength = [textField offsetFromPosition:selectedRange.start toPosition:selectedRange.end];
    // 没有高亮内容时,对已输入的文字进行操作
    if (markedTextLength == 0) {
        if (contentText.length > self.xq_limitTextLength) {
            // 此方法用于在字符串的一个range范围内,返回此range范围内完整的字符串的range.(eg:😈)
            NSRange rangeRange = [contentText rangeOfComposedCharacterSequencesForRange:NSMakeRange(0, self.xq_limitTextLength)];
            NSString *rsStr = [contentText substringWithRange:rangeRange];
            textField.text = rsStr;
        }
    }
}

@end

使用的时候就只需要设置textField.xq_limitTextLength = 10;就OK了,当输入超过10个字符时,将不能够再输入.

UITextView的分类:

@interface UITextView (XQHelper)

//限制UITextView的输入字数.0表示无限制.
@property (nonatomic, assign) NSInteger xq_limitTextLength;

@end

实现:

@implementation UITextView (XQHelper)

- (NSInteger)xq_limitTextLength
{
    NSNumber *limit = objc_getAssociatedObject(self, @selector(xq_limitTextLength));
    return limit.integerValue;
}

- (void)setXq_limitTextLength:(NSInteger)xq_limitTextLength
{
    objc_setAssociatedObject(self, @selector(xq_limitTextLength), @(xq_limitTextLength), OBJC_ASSOCIATION_ASSIGN);
    
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextViewTextDidChangeNotification object:self];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textViewTextDidChanged:) name:UITextViewTextDidChangeNotification object:self];
}

- (void)textViewTextDidChanged:(NSNotification *)notify
{
    if (self.xq_limitTextLength <= 0) {
        return;
    }
    
    UITextView *textView = notify.object;
    
    UITextRange *selectedRange = [textView markedTextRange];
    //获取高亮部分
    UITextPosition *pos = [textView positionFromPosition:selectedRange.start offset:0];
    
    //如果在变化中是高亮部分在变,就不要计算字符了.防止系统中文键盘输入bug
    if (selectedRange && pos) {
        return;
    }
    
    NSRange selection = textView.selectedRange;
    
    NSInteger realLength = textView.text.length; //实际总长度
    
    NSString *headText = [textView.text substringToIndex:selection.location]; //光标前的文本
    NSString *tailText = [textView.text substringFromIndex:selection.location]; //光标后的文本
    
    NSInteger restLength = self.xq_limitTextLength - tailText.length; //光标后允许输入的文本长度
    
    if (realLength > self.xq_limitTextLength) {
        NSString *subHeadText = [headText substringToIndex:restLength];
        textView.text = [subHeadText stringByAppendingString:tailText];
        [textView setSelectedRange:NSMakeRange(restLength, 0)];
    }
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextViewTextDidChangeNotification object:self];
}

@end

使用:textView.xq_limitTextLength = 10;
其中在系统中文键盘输入时,因为输入联想的原因,限制时需要做一些判断.
参考:
iOS UITextField限制字符长度