iOS UITextView限制输入字数并显示剩余字数

#define MAX_LIMIT_NUMS 255
self . textNumLab 为显示剩余字数的label

#pragma mark - 限制病情描述输入字数 ( 最多不超过 255 个字 )
- ( BOOL )textView:( UITextView *)textView shouldChangeTextInRange:( NSRange )range replacementText:( NSString *)text{
    // 不支持系统表情的输入
     if ([[textView  textInputMode primaryLanguage ]== nil ||[[[textView  textInputMode primaryLanguage ] isEqualToString : @"emoji" ]) {
        return NO ;
    }
    UITextRange *selectedRange = [textView  markedTextRange ];
     // 获取高亮部分
    UITextPosition *pos = [textView  positionFromPosition :selectedRange. start offset : 0 ];
    // 获取高亮部分内容  
     //NSString * selectedtext = [textView textInRange:selectedRange];
    // 如果有高亮且当前字数开始位置小于最大限制时允许输入
    if (selectedRange && pos) {   
        NSInteger startOffset = [textView  offsetFromPosition :textView. beginningOfDocument  toPosition :selectedRange. start ];
        NSInteger endOffset = [textView  offsetFromPosition :textView. beginningOfDocument  toPosition :selectedRange. end ];        
        NSRange offsetRange = NSMakeRange (startOffset, endOffset - startOffset);
        if (offsetRange. location < MAX_LIMIT_NUMS ) {
          return  YES ;
        } else {             
            return  NO ;   
        }      
    }
    NSString *comcatstr = [textView. text  stringByReplacingCharactersInRange :range  withString :text];
    NSInteger caninputlen = MAX_LIMIT_NUMS - comcatstr. length
    if (caninputlen >= 0 ){
        return  YES ;
    } else {    
        NSInteger len = text. length + caninputlen;
         // 防止当 text.length + caninputlen < 0 时,使得 rg.length 为一个非法最大正数出错       
        NSRange rg = { 0 , MAX (len, 0 )};  
        if (rg. length > 0 ){
            NSString *s = @"" ;
             // 判断是否只普通的字符或 asc ( 对于中文和表情返回 NO)
             BOOL asc = [text  canBeConvertedToEncoding : NSASCIIStringEncoding ];
            if (asc) {
                s = [text  substringWithRange :rg]; // 因为是 ascii 码直接取就可以了不会错
            } else {
                __block  NSInteger idx = 0 ;
                __block  NSString   *trimString = @"" ; // 截取出的字串
                 // 使用字符串遍历,这个方法能准确知道每个 emoji 是占一个 unicode 还是两个
                [text  enumerateSubstringsInRange : NSMakeRange ( 0 , [text  length ])
                                         options : NSStringEnumerationByComposedCharacterSequences
                                      usingBlock : ^( NSString * substring, NSRange substringRange, NSRange enclosingRange, BOOL * stop) {
                                          if (idx >= rg. length ) {                                              
                                              *stop = YES ; // 取出所需要就 break ,提高效率
                                              return ;                                            
                                          }
                                          trimString = [trimString  stringByAppendingString :substring];
                                          idx++;
                                      }];
                s = trimString;
            }
            //rang 是指从当前光标处进行替换处理 ( 注意如果执行此句后面返回的是 YES 会触发 didchange 事件 )
            [textView  setText :[textView. text  stringByReplacingCharactersInRange :range withString :s]];
            // 既然是超出部分截取了,哪一定是最大限制了。
            self . textNumLab . text = [ NSString  stringWithFormat : @"%d/%ld" , 0 ,( long ) MAX_LIMIT_NUMS ];           
        }      
        return NO ;       
    }
}

#pragma mark - 显示当前可输入字数 / 总字数
- ( void )textViewDidChange:( UITextView *)textView{
    UITextRange *selectedRange = [textView  markedTextRange ];    
     // 获取高亮部分
    UITextPosition *pos = [textView  positionFromPosition :selectedRange. start offset : 0 ];
    // 如果在变化中是高亮部分在变,就不要计算字符了
    if (selectedRange && pos) {
        return ;     
    }
    NSString   *nsTextContent = textView. text ;
    NSInteger existTextNum = nsTextContent. length ;
    if (existTextNum > MAX_LIMIT_NUMS ){
        // 截取到最大位置的字符 ( 由于超出截部分在 should 时被处理了所在这里这了提高效率不再判断 )         
        NSString *s = [nsTextContent  substringToIndex : MAX_LIMIT_NUMS ];
        [textView setText :s];         
    }
     // 不让显示负数
    self . textNumLab . text = [ NSString stringWithFormat : @"%ld/%d" , MAX ( 0 , MAX_LIMIT_NUMS - existTextNum), MAX_LIMIT_NUMS ];

}


效果如图:


参考地址:http://www.it165.net/pro/html/201505/39736.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值