198 lines
6.9 KiB
Objective-C
198 lines
6.9 KiB
Objective-C
//
|
||
// EGInputLimit.m
|
||
// EGCommon
|
||
//
|
||
// Created by donglyu on 2020/4/20.
|
||
// Copyright © 2020 Company. All rights reserved.
|
||
//
|
||
|
||
#import "EGInputLimit.h"
|
||
#import <objc/runtime.h>
|
||
|
||
NSString *const WSInputLimitOnlyNumbersPattern = @"[0-9]+";
|
||
NSString *const WSInputLimitOnlyChinesePattern = @"[\u4e00-\u9fa5]+";
|
||
NSString *const WSInputLimitOnlyLetterPattern = @"[A-Za-z]+";
|
||
/// 处理emoji符号,数值、各语言字母不会处理
|
||
NSString *const WSInputLimitFilterEmojiPattern = @"[\U0001f0a0-\U0001f0ff\U0001f170-\U0001f19a\U0001f300-\U0001faff\u2190-\u21FF\u2300-\u23FF\u2500-\u26FF\u2700-\u27BF\u27F0-\u27FF\u2900-\u297F\u2B00-\u2BFF]+";
|
||
// 下方是旧正则、部分其他语言的文案不通过,eg: évaluation
|
||
//@"[^\\u0020-\\u007E\\u00A0-\\u00BE\\u2E80-\\uA4CF\\uF900-\\uFAFF\\uFE30-\\uFE4F\\uFF00-\\uFFEF\\u0080-\\u009F\\u2000-\\u201f\r\n]";
|
||
|
||
static inline NSString *WSInputLimitDecimaStylePattern(NSInteger decimalPlace) {
|
||
return [NSString stringWithFormat:@"([1-9][0-9]*|0)(\\.)?([0-9]{1,%ld})?", MAX(1, decimalPlace)];
|
||
}
|
||
|
||
|
||
@interface EGInputLimit()
|
||
@property (nonatomic, weak, readonly) UITextField *textField;
|
||
@property (nonatomic, weak, readonly) UITextView *textView;
|
||
@end
|
||
|
||
@implementation EGInputLimit
|
||
|
||
- (void)dealloc
|
||
{
|
||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||
}
|
||
|
||
- (instancetype)initWithTextField:(UITextField *)textField {
|
||
if (self = [super init]) {
|
||
_textField = textField;
|
||
|
||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldTextDidChange:) name:UITextFieldTextDidChangeNotification object:_textField];
|
||
}
|
||
return self;
|
||
}
|
||
|
||
- (instancetype)initWithTextView:(UITextView *)textView {
|
||
if (self = [super init]) {
|
||
_textView = textView;
|
||
|
||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textViewTextDidChange:) name:UITextViewTextDidChangeNotification object:_textView];
|
||
}
|
||
return self;
|
||
}
|
||
|
||
#pragma mark textFieldTextDidChange
|
||
- (void)textFieldTextDidChange:(NSNotification *)notifi {
|
||
if (_disable) {
|
||
return;
|
||
}
|
||
UITextField *textField = notifi.object;
|
||
if (textField == _textField) {
|
||
UITextRange *markedTextRange = [_textField markedTextRange];
|
||
UITextPosition *position = [_textField positionFromPosition:markedTextRange.start offset:0];
|
||
if (markedTextRange && position) {
|
||
return;
|
||
}
|
||
|
||
NSString *result = [self handleText:_textField.text];
|
||
UITextRange* selectedRange = _textField.selectedTextRange;
|
||
_textField.text = result;
|
||
_textField.selectedTextRange = selectedRange;
|
||
}
|
||
}
|
||
|
||
#pragma mark textViewTextDidChange
|
||
- (void)textViewTextDidChange:(NSNotification *)notifi {
|
||
if (_disable) {
|
||
return;
|
||
}
|
||
UITextView *textView = notifi.object;
|
||
if (textView == _textView) {
|
||
UITextRange *markedTextRange = [_textView markedTextRange];
|
||
UITextPosition *position = [_textView positionFromPosition:markedTextRange.start offset:0];
|
||
if (markedTextRange && position) {
|
||
return;
|
||
}
|
||
|
||
NSString *result = [self handleText:_textView.text];
|
||
NSRange selectedRange = _textView.selectedRange;
|
||
_textView.text = result;
|
||
_textView.selectedRange = NSMakeRange(selectedRange.location, 0);
|
||
}
|
||
}
|
||
|
||
- (NSString *)handleText:(NSString *)text {
|
||
if (_onlyNumbers) {
|
||
NSString *result = [self subStringFromText:text withPattern:WSInputLimitOnlyNumbersPattern];
|
||
return result;
|
||
}
|
||
|
||
if (_onlyChinese) {
|
||
NSString *result = [self subStringFromText:text withPattern:WSInputLimitOnlyChinesePattern];
|
||
return result;
|
||
}
|
||
|
||
if (_onlyLetter) {
|
||
NSString *result = [self subStringFromText:text withPattern:WSInputLimitOnlyLetterPattern];
|
||
return result;
|
||
}
|
||
|
||
if (_decimaStyle) {
|
||
NSString *pattern = WSInputLimitDecimaStylePattern(_decimalPlace);
|
||
NSString *result = [self subStringFromText:text withPattern:pattern];
|
||
return result;
|
||
}
|
||
|
||
if (_allowPattern) {
|
||
NSString *result = [self subStringFromText:text withPattern:_allowPattern];
|
||
return result;
|
||
}
|
||
|
||
NSString *filterPattern = _filterPattern;
|
||
if (_disableEmoji) {
|
||
filterPattern = WSInputLimitFilterEmojiPattern;
|
||
}
|
||
if (filterPattern) {
|
||
NSRegularExpression *regex = [[NSRegularExpression alloc]initWithPattern:filterPattern options:0 error:NULL];
|
||
NSString *result = [regex stringByReplacingMatchesInString:text
|
||
options:0
|
||
range:NSMakeRange(0, text.length)
|
||
withTemplate:@""];
|
||
result = [self lengthHandle:result];
|
||
return result;
|
||
}
|
||
|
||
NSString *result = [self lengthHandle:text];
|
||
return result;
|
||
}
|
||
|
||
- (NSString *)subStringFromText:(NSString *)string withPattern:(NSString *)pattern {
|
||
NSRange range = [string rangeOfString:pattern
|
||
options:NSRegularExpressionSearch
|
||
range:NSMakeRange(0, string.length)];
|
||
NSString *result = @"";
|
||
if (range.location != NSNotFound) {
|
||
result = [string substringWithRange:range];
|
||
}
|
||
result = [self lengthHandle:result];
|
||
return result;
|
||
}
|
||
|
||
- (NSString *)lengthHandle:(NSString *)text {
|
||
__block NSString *filterText = @"";
|
||
__block NSInteger currentChatNum = 0;
|
||
NSInteger maxCharacterNumber = _maxCharacterNumber;
|
||
[text enumerateSubstringsInRange:NSMakeRange(0, text.length)
|
||
options:NSStringEnumerationByComposedCharacterSequences
|
||
usingBlock:^(NSString * _Nullable substring, NSRange substringRange, NSRange enclosingRange, BOOL * _Nonnull stop) {
|
||
if (maxCharacterNumber > 0 && currentChatNum >= maxCharacterNumber) {
|
||
*stop = YES;
|
||
} else {
|
||
filterText = [filterText stringByAppendingString:substring];
|
||
currentChatNum ++;
|
||
}
|
||
}];
|
||
_currentCharNumber = currentChatNum;
|
||
_canEnterCharNumber = MAX(0, _maxCharacterNumber - _currentCharNumber);
|
||
return filterText;
|
||
}
|
||
|
||
@end
|
||
|
||
@implementation UITextView (WSInputLimit)
|
||
|
||
- (EGInputLimit *)limit {
|
||
EGInputLimit *limit = objc_getAssociatedObject(self, _cmd);
|
||
if (!limit) {
|
||
limit = [[EGInputLimit alloc]initWithTextView:self];
|
||
objc_setAssociatedObject(self, _cmd, limit, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||
}
|
||
return limit;
|
||
}
|
||
|
||
@end
|
||
|
||
@implementation UITextField (WSInputLimit)
|
||
|
||
- (EGInputLimit *)limit {
|
||
EGInputLimit *limit = objc_getAssociatedObject(self, _cmd);
|
||
if (!limit) {
|
||
limit = [[EGInputLimit alloc]initWithTextField:self];
|
||
objc_setAssociatedObject(self, _cmd, limit, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||
}
|
||
return limit;
|
||
}
|
||
|
||
@end
|