XLTextCalculateHelper.m 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. //
  2. // XLTextCalculateHelper.m
  3. // amigo
  4. //
  5. // Created by wujian on 2017/9/30.
  6. // Copyright © 2017年 xiaolian.Inc. All rights reserved.
  7. //
  8. #import "XLTextCalculateHelper.h"
  9. @implementation XLTextCalculateHelper
  10. + (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string textLimit:(NSUInteger)textLimit
  11. {
  12. UITextRange *selectedRange = [textField markedTextRange];
  13. //获取高亮部分
  14. UITextPosition *pos = [textField positionFromPosition:selectedRange.start offset:0];
  15. //获取高亮部分内容
  16. //NSString * selectedtext = [textView textInRange:selectedRange];
  17. //如果有高亮且当前字数开始位置小于最大限制时允许输入
  18. if (selectedRange && pos) {
  19. NSInteger startOffset = [textField offsetFromPosition:textField.beginningOfDocument toPosition:selectedRange.start];
  20. NSInteger endOffset = [textField offsetFromPosition:textField.beginningOfDocument toPosition:selectedRange.end];
  21. NSRange offsetRange = NSMakeRange(startOffset, endOffset - startOffset);
  22. if (offsetRange.location < textLimit) {
  23. return YES;
  24. }
  25. else
  26. {
  27. return NO;
  28. }
  29. }
  30. NSString *comcatstr = [textField.text stringByReplacingCharactersInRange:range withString:string];
  31. NSInteger caninputlen = textLimit - comcatstr.length;
  32. if (caninputlen >= 0)
  33. {
  34. return YES;
  35. }
  36. else
  37. {
  38. NSInteger len = string.length + caninputlen;
  39. //防止当text.length + caninputlen < 0时,使得rg.length为一个非法最大正数出错
  40. NSRange rg = {0,MAX(len,0)};
  41. if (rg.length > 0)
  42. {
  43. NSString *s = @"";
  44. //判断是否只普通的字符或asc码(对于中文和表情返回NO)
  45. BOOL asc = [string canBeConvertedToEncoding:NSASCIIStringEncoding];
  46. if (asc) {
  47. s = [string substringWithRange:rg];//因为是ascii码直接取就可以了不会错
  48. }
  49. else
  50. {
  51. __block NSInteger idx = 0;
  52. __block NSString *trimString = @"";//截取出的字串
  53. //使用字符串遍历,这个方法能准确知道每个emoji是占一个unicode还是两个
  54. [string enumerateSubstringsInRange:NSMakeRange(0, [string length])
  55. options:NSStringEnumerationByComposedCharacterSequences
  56. usingBlock: ^(NSString* substring, NSRange substringRange, NSRange enclosingRange, BOOL* stop) {
  57. if (idx >= rg.length) {
  58. *stop = YES; //取出所需要就break,提高效率
  59. return ;
  60. }
  61. trimString = [trimString stringByAppendingString:substring];
  62. idx++;
  63. }];
  64. s = trimString;
  65. }
  66. //rang是指从当前光标处进行替换处理(注意如果执行此句后面返回的是YES会触发didchange事件)
  67. [textField setText:[textField.text stringByReplacingCharactersInRange:range withString:s]];
  68. }
  69. return NO;
  70. }
  71. }
  72. + (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text textLimit:(NSUInteger)textLimit
  73. {
  74. UITextRange *selectedRange = [textView markedTextRange];
  75. //获取高亮部分
  76. UITextPosition *pos = [textView positionFromPosition:selectedRange.start offset:0];
  77. //获取高亮部分内容
  78. //NSString * selectedtext = [textView textInRange:selectedRange];
  79. //如果有高亮且当前字数开始位置小于最大限制时允许输入
  80. if (selectedRange && pos) {
  81. NSInteger startOffset = [textView offsetFromPosition:textView.beginningOfDocument toPosition:selectedRange.start];
  82. NSInteger endOffset = [textView offsetFromPosition:textView.beginningOfDocument toPosition:selectedRange.end];
  83. NSRange offsetRange = NSMakeRange(startOffset, endOffset - startOffset);
  84. if (offsetRange.location < textLimit) {
  85. return YES;
  86. }
  87. else
  88. {
  89. return NO;
  90. }
  91. }
  92. NSString *comcatstr = [textView.text stringByReplacingCharactersInRange:range withString:text];
  93. NSInteger caninputlen = textLimit - comcatstr.length;
  94. if (caninputlen >= 0)
  95. {
  96. return YES;
  97. }
  98. else
  99. {
  100. NSInteger len = text.length + caninputlen;
  101. //防止当text.length + caninputlen < 0时,使得rg.length为一个非法最大正数出错
  102. NSRange rg = {0,MAX(len,0)};
  103. if (rg.length > 0)
  104. {
  105. NSString *s = @"";
  106. //判断是否只普通的字符或asc码(对于中文和表情返回NO)
  107. BOOL asc = [text canBeConvertedToEncoding:NSASCIIStringEncoding];
  108. if (asc) {
  109. s = [text substringWithRange:rg];//因为是ascii码直接取就可以了不会错
  110. }
  111. else
  112. {
  113. __block NSInteger idx = 0;
  114. __block NSString *trimString = @"";//截取出的字串
  115. //使用字符串遍历,这个方法能准确知道每个emoji是占一个unicode还是两个
  116. [text enumerateSubstringsInRange:NSMakeRange(0, [text length])
  117. options:NSStringEnumerationByComposedCharacterSequences
  118. usingBlock: ^(NSString* substring, NSRange substringRange, NSRange enclosingRange, BOOL* stop) {
  119. if (idx >= rg.length) {
  120. *stop = YES; //取出所需要就break,提高效率
  121. return ;
  122. }
  123. trimString = [trimString stringByAppendingString:substring];
  124. idx++;
  125. }];
  126. s = trimString;
  127. }
  128. //rang是指从当前光标处进行替换处理(注意如果执行此句后面返回的是YES会触发didchange事件)
  129. [textView setText:[textView.text stringByReplacingCharactersInRange:range withString:s]];
  130. }
  131. return NO;
  132. }
  133. }
  134. + (BOOL)textFieldDidChangeWillContinue:(UITextField *)textField textLimit:(NSUInteger)textLimit
  135. {
  136. UITextRange *selectedRange = [textField markedTextRange];
  137. //获取高亮部分
  138. UITextPosition *pos = [textField positionFromPosition:selectedRange.start offset:0];
  139. //如果在变化中是高亮部分在变,就不要计算字符了
  140. if (selectedRange && pos) {
  141. return NO;
  142. }
  143. NSString *nsTextContent = textField.text;
  144. NSInteger existTextNum = nsTextContent.length;
  145. if (existTextNum > textLimit)
  146. {
  147. //截取到最大位置的字符(由于超出截部分在should时被处理了所在这里这了提高效率不再判断)
  148. NSString *s = [nsTextContent substringToIndex:textLimit];
  149. [textField setText:s];
  150. }
  151. return YES;
  152. }
  153. + (BOOL)textViewDidChangeWillContinue:(UITextView *)textView textLimit:(NSUInteger)textLimit
  154. {
  155. UITextRange *selectedRange = [textView markedTextRange];
  156. //获取高亮部分
  157. UITextPosition *pos = [textView positionFromPosition:selectedRange.start offset:0];
  158. //如果在变化中是高亮部分在变,就不要计算字符了
  159. if (selectedRange && pos) {
  160. return NO;
  161. }
  162. NSString *nsTextContent = textView.text;
  163. NSInteger existTextNum = nsTextContent.length;
  164. if (existTextNum > textLimit)
  165. {
  166. //截取到最大位置的字符(由于超出截部分在should时被处理了所在这里这了提高效率不再判断)
  167. NSString *s = [nsTextContent substringToIndex:textLimit];
  168. [textView setText:s];
  169. }
  170. return YES;
  171. }
  172. @end