UITextField 支持内容滚动、3位数字间空格分割、禁止选
2022-10-23 本文已影响0人
简繁之间_来去自然
1
textFieldScrollable.gif
2
textFieldSpace.gif
1 支持滚动
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSUInteger, TextRangeChangedType) {
TextRangeChangedTypeLeftAndBack,
TextRangeChangedTypeLeftAndForward,
TextRangeChangedTypeRightAndBack,
TextRangeChangedTypeRightAndForward,
TextRangeChangedTypeNone
};
NS_ASSUME_NONNULL_BEGIN
@interface ZTextFieldScrollable : UIView
@property (nonatomic, readonly, strong) UITextField *textField;
@end
typedef void(^SelectedTextRangeChangedBlock)(TextRangeChangedType changeType, CGFloat beforeTextWidth);
@interface InnerTextField : UITextField
- (nullable NSNumber *)getWidthFromDocumentBeginingToCursor;
- (nullable NSNumber *)getWidthFromDocumentBeginingToEnd;
@property (nonatomic, strong) SelectedTextRangeChangedBlock selectedTextRangeChangedBlock;
@end
NS_ASSUME_NONNULL_END
#import "ZTextFieldScrollable.h"
static const CGFloat kOneCutWidth = 41;
static const CGFloat kDefaultCutTimes = 3;
@interface ZTextFieldScrollable () <UIScrollViewDelegate, UIGestureRecognizerDelegate,UITextFieldDelegate>
@property (nonatomic, strong) UITextField *textField;
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UITapGestureRecognizer *tapGesture;
@property (nonatomic, strong) NSLayoutConstraint *textFiledWidthConstraint;
@end
@implementation ZTextFieldScrollable
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self configureSubviews];
}
return self;
}
- (void)configureSubviews {
// scroll
_scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
_scrollView.contentSize = CGSizeMake(kOneCutWidth * kDefaultCutTimes, 0);
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.bounces = NO;
_scrollView.delegate = self;
_scrollView.backgroundColor = UIColor.greenColor;
[self addSubview:_scrollView];
_scrollView.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutConstraint *scrollLeftCons = [NSLayoutConstraint constraintWithItem:_scrollView
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeLeft
multiplier:1
constant:0];
NSLayoutConstraint *scrollRightCons = [NSLayoutConstraint constraintWithItem:_scrollView
attribute:NSLayoutAttributeRight
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeRight
multiplier:1
constant:0];
NSLayoutConstraint *scrollTopCons = [NSLayoutConstraint constraintWithItem:_scrollView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeTop
multiplier:1
constant:0];
NSLayoutConstraint *scrollBottomCons = [NSLayoutConstraint constraintWithItem:_scrollView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeBottom
multiplier:1
constant:0];
[self addConstraints:@[scrollLeftCons, scrollRightCons, scrollTopCons, scrollBottomCons]];
// text field
InnerTextField *newTextField = [[InnerTextField alloc] initWithFrame:CGRectZero];
// newTextField.delegate = self;
_textField = newTextField;
[newTextField addTarget:self action:@selector(handleTextField) forControlEvents:UIControlEventEditingChanged];
_tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
_tapGesture.delegate = self;
[newTextField addGestureRecognizer:_tapGesture];
__weak typeof(self) ws = self;
newTextField.selectedTextRangeChangedBlock = ^(TextRangeChangedType changeType, CGFloat beforeTextWidth) {
__strong typeof(self) ss = ws;
if (!ss) {
return;
}
CGFloat div = 15;
CGPoint originOffset = ss->_scrollView.contentOffset;
if (beforeTextWidth < ss->_scrollView.contentOffset.x + div) {
[UIView animateWithDuration:0.1 animations:^{
ss->_scrollView.contentOffset = CGPointMake(MAX(beforeTextWidth - div, 0), originOffset.y);
}];
} else if (beforeTextWidth > originOffset.x + ss->_scrollView.bounds.size.width - div) {
[UIView animateWithDuration:0.1 animations:^{
ss->_scrollView.contentOffset = CGPointMake(beforeTextWidth - ss->_scrollView.bounds.size.width + div, originOffset.y);
}];
}
};
[_scrollView addSubview:newTextField];
newTextField.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutConstraint *textLeftCons = [NSLayoutConstraint constraintWithItem:newTextField
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:_scrollView
attribute:NSLayoutAttributeLeft
multiplier:1
constant:0];
NSLayoutConstraint *textTopCons = [NSLayoutConstraint constraintWithItem:newTextField
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeTop
multiplier:1
constant:0];
NSLayoutConstraint *textBottomCons = [NSLayoutConstraint constraintWithItem:newTextField
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeBottom
multiplier:1
constant:0];
NSLayoutConstraint *textWidthCons = [NSLayoutConstraint constraintWithItem:newTextField
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:kOneCutWidth * kDefaultCutTimes];
[_scrollView addConstraint:textLeftCons];
[self addConstraints:@[textTopCons, textBottomCons]];
[newTextField addConstraint:textWidthCons];
_textFiledWidthConstraint = textWidthCons;
}
- (void)handleTextField {
InnerTextField *hookedTF = (InnerTextField *)_textField;
if (![hookedTF isKindOfClass:InnerTextField.class]) {
return;
}
NSNumber *width = [hookedTF getWidthFromDocumentBeginingToCursor];
NSNumber *fullWidth = [hookedTF getWidthFromDocumentBeginingToEnd];
if (!width || !fullWidth) {
return;
}
CGFloat selfWidth = self.bounds.size.width;
if (selfWidth == 0) {
return;
}
//check max bounds
CGSize originContentSize = _scrollView.contentSize;
if (_scrollView.contentSize.width - fullWidth.doubleValue < kOneCutWidth) {
if (_scrollView.contentSize.width <= fullWidth.doubleValue) {
_scrollView.contentSize = CGSizeMake(fullWidth.doubleValue + kOneCutWidth, originContentSize.height);
} else {
_scrollView.contentSize = CGSizeMake(originContentSize.width + kOneCutWidth, originContentSize.height);
}
_textFiledWidthConstraint.constant = _scrollView.contentSize.width;
[self layoutIfNeeded];
}
CGPoint originOffset = _scrollView.contentOffset;
if (width.doubleValue >= selfWidth - 3) {
if (width.doubleValue - originOffset.x >= 0 && width.doubleValue - originOffset.x < selfWidth) {
return;
}
CGFloat diff = MAX(width.doubleValue - selfWidth + 3, 0);
_scrollView.contentOffset = CGPointMake(diff, originOffset.y);
} else {
_scrollView.contentOffset = CGPointMake(0, originOffset.y);
}
}
- (void)handleTap:(UITapGestureRecognizer *)gesture {
CGPoint point = [gesture locationInView:_textField];
UITextPosition *closestPosition = [_textField closestPositionToPoint:point];
if (closestPosition) {
_textField.selectedTextRange = [_textField textRangeFromPosition:closestPosition toPosition:closestPosition];
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
InnerTextField *textField = (InnerTextField *)_textField;
if (![textField isKindOfClass:InnerTextField.class]) {
return;
}
NSNumber *currentTextWidth = [textField getWidthFromDocumentBeginingToEnd];
if (!currentTextWidth) {
return;
}
CGFloat selfWidth = self.frame.size.width;
CGPoint originOffset = _scrollView.contentOffset;
if (currentTextWidth.doubleValue < selfWidth) {
_scrollView.contentOffset = CGPointMake(0, originOffset.y);
return;
}
CGFloat maxOffsetX = currentTextWidth.doubleValue - selfWidth + 6;
if (_scrollView.contentOffset.x > maxOffsetX) {
_scrollView.contentOffset = CGPointMake(maxOffsetX, originOffset.y);
}
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if (gestureRecognizer == self.tapGesture) {
return _textField.isFirstResponder;
}
return YES;
}
@end
@implementation InnerTextField
- (nullable NSNumber *)getWidthFromDocumentBeginingToCursor {
UITextRange *selectedRange = self.selectedTextRange;
if (selectedRange) {
return [self getWidthFromDocumentBeginingToPosition:selectedRange.start];
}
return nil;
}
- (nullable NSNumber *)getWidthFromDocumentBeginingToEnd {
NSString *str = self.text;
if (str) {
return @([self getWidthFromString:str]);
}
return nil;
}
- (TextRangeChangedType)changeTypeFromOldRange:(UITextRange *)oldRange toNewRange:(UITextRange *)newRange {
NSInteger oldStart = [self offsetFromPosition:self.beginningOfDocument toPosition:oldRange.start];
NSInteger oldEnd = [self offsetFromPosition:self.beginningOfDocument toPosition:oldRange.end];
NSInteger newStart = [self offsetFromPosition:self.beginningOfDocument toPosition:newRange.start];
NSInteger newEnd = [self offsetFromPosition:self.beginningOfDocument toPosition:newRange.end];
if (oldStart == newStart && oldEnd != newEnd) {
if (newEnd > oldEnd) {
return TextRangeChangedTypeRightAndForward;
} else if (newEnd < oldEnd) {
return TextRangeChangedTypeRightAndBack;
}
return TextRangeChangedTypeNone;
}
if (oldStart != newStart && oldEnd == newEnd) {
if (newStart < oldStart) {
return TextRangeChangedTypeLeftAndBack;
} else if (newStart > oldStart) {
return TextRangeChangedTypeLeftAndForward;
}
return TextRangeChangedTypeNone;
}
if (oldStart == oldEnd && newStart == newEnd) {
if (newStart > oldStart) {
return TextRangeChangedTypeRightAndForward;
} else if (newStart < oldStart) {
return TextRangeChangedTypeLeftAndBack;
}
}
return TextRangeChangedTypeNone;
}
- (CGFloat)getWidthFromString:(NSString *)text {
UILabel *newLabel = [[UILabel alloc] initWithFrame:CGRectZero];
newLabel.text = text;
UIFont *font = self.font ? : [UIFont systemFontOfSize:15];
newLabel.font = font;
[newLabel sizeToFit];
return newLabel.bounds.size.width;
}
- (nullable NSNumber *)getWidthFromDocumentBeginingToPosition:(UITextPosition *)position {
NSString *curText = self.text;
if (!curText) {
return nil;
}
NSInteger offset = [self offsetFromPosition:self.beginningOfDocument toPosition:position];
if (offset <= curText.length && offset >= 0) {
NSString *subStr = [curText substringToIndex:offset];
CGFloat width = [self getWidthFromString:subStr];
return @(width);
} else {
return nil;
}
}
- (void)setText:(NSString *)text {
[super setText:text];
[self sendActionsForControlEvents:UIControlEventEditingChanged];
}
- (void)setSelectedTextRange:(UITextRange *)selectedTextRange {
UITextRange *oldVal = self.selectedTextRange;
UITextRange *newVal = selectedTextRange;
if (oldVal && newVal) {
TextRangeChangedType willChangeType = [self changeTypeFromOldRange:oldVal toNewRange:newVal];
NSNumber *width = nil;
if (willChangeType == TextRangeChangedTypeLeftAndBack || willChangeType == TextRangeChangedTypeLeftAndForward) {
width = [self getWidthFromDocumentBeginingToPosition:newVal.start];
} else if (willChangeType == TextRangeChangedTypeRightAndForward || willChangeType == TextRangeChangedTypeRightAndBack) {
width = [self getWidthFromDocumentBeginingToPosition:newVal.end];
}
if (width && _selectedTextRangeChangedBlock) {
_selectedTextRangeChangedBlock(willChangeType, width.floatValue);
}
}
[super setSelectedTextRange:selectedTextRange];
}
@end
2.0 支持3位数字空格分割 - extension
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UITextField (ZYFTextField)
/// 自动遵守代理, 若外界使用代理则可能会覆盖本方法, 外界使用代理时请使用 kDealStringWithSpace
- (void)kInitSpace;
/// 接收数据并展示为 空格拼接样式, 部分拦截场景会返回NO则需要shouldChangeCharactersInRange中return NO;
/// @param string 每次输入的字符
- (BOOL)kDealStringWithSpace:(NSString *)string range:(NSRange)range;
/// 获取当前真实数据, 不包含空格
- (NSString *)kGetRealString;
@end
NS_ASSUME_NONNULL_END
/** 使用场景1, 外界无需使用代理时
* [textField kInitSpace];
* 获取真实文案 if Need
* [self.textField kGetRealString];
*/
/** 使用场景2, 外界需要使用代理时
*
* textField.delegate = self;
*
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
if (![textField kDealStringWithSpace:string]) {
return NO;
}
return YES;
}
*
* 获取真实文案 if Need
* [self.textField kGetRealString];
*/
#import "UITextField+ZYFTextField.h"
#import <objc/runtime.h>
@interface UITextField (ZYFTextField)<UITextFieldDelegate>
@property (nonatomic, copy) NSString * kRealString; // 当前所有展示数据
@property (nonatomic, copy) NSNumber * kHasSpace; // 输入位数是否触发添加空格
@end
@implementation UITextField (ZYFTextField)
@dynamic kRealString;
@dynamic kHasSpace;
-(void)setKRealString:(NSString *)kRealString{
objc_setAssociatedObject(self, @selector(kRealString), kRealString, OBJC_ASSOCIATION_COPY);
}
- (NSString *)kRealString{
return objc_getAssociatedObject(self,_cmd);
}
-(void)setKHasSpace:(NSNumber *)kHasSpace{
objc_setAssociatedObject(self, @selector(kHasSpace), kHasSpace, OBJC_ASSOCIATION_COPY);
}
- (NSNumber *)kHasSpace{
return objc_getAssociatedObject(self,_cmd);
}
- (void)kInitSpace{
self.delegate = self;
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
NSLog(@"--==-s exten : %@---",string);
if (![self kDealStringWithSpace:string range:range]) {
return NO;
}
return YES;
}
- (NSString *)kGetRealString{
if (self.kRealString) {
return self.kRealString;
}
return @"";
}
- (BOOL)kDealStringWithSpace:(NSString *)string range:(NSRange)range{
NSString * realStr = [self.text stringByReplacingCharactersInRange:range withString:string];
if (!self.kRealString) {
self.kRealString = @"";
}
/// 非数字 且 非删除 return false
BOOL isDelete = [string isEqualToString:@""];
self.kRealString = [realStr stringByReplacingOccurrencesOfString:@" " withString:@""];
// 2 符合规则后 更新展示1
[self updateShow:!isDelete range:range string:string];
// 3 部分拦截场景
if ([self kShouldReturn:!isDelete]) {
return NO;
}
return YES;
}
/// 展示带有空格分割的文本
/// @param isAdd 是否是输入操作
- (void)updateShow:(BOOL)isAdd range:(NSRange)range string:(NSString *)string{
NSInteger realCount = self.kRealString.length;
if (realCount >= 6) {
self.kHasSpace = @1;
NSInteger type = 0;
if (realCount % 3 == 0) {
type = 3;
}else if(realCount % 4 == 0) {
type = 4;
}
if (type > 0) {
NSInteger currentSpaces = [self.text componentsSeparatedByString:@" "].count - 1;
self.text = [self kFilterWithType:type];
NSInteger totalSpace = [self kGetTotalSpace:type] - 1;
currentSpaces = MAX(currentSpaces, 0);
totalSpace = MAX(totalSpace, 0);
NSInteger dif = totalSpace - currentSpaces;
if (isAdd) {
dif ++;
}
NSRange newRange = NSMakeRange(range.location + dif , 0);
if (string.length > 1) {
NSInteger length = self.text.length;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self setSelectedRange:NSMakeRange(length, 0)];
});
}else{
[self setSelectedRange:newRange];
}
}
}else if (realCount >= 3){
if (!isAdd) {
if (realCount % 3 == 0 && [self.kHasSpace integerValue] == 1) {
self.text = [self kFilterWithType:3];
}
}
}else{
if (!isAdd) {
self.kHasSpace = @0;
}
}
}
- (NSInteger)kGetTotalSpace:(NSInteger)type{
NSString * str = self.kRealString;
NSInteger count = str.length;
NSInteger total = 0;
if (type == 3 || type == 4) {
if (str.length % type == 0) {
total = count / type;
}
}
return total;
}
/// 传入位数 , 根据位数动态拼接
/// @param type 位数
- (NSString *)kFilterWithType:(NSInteger)type{
NSString * str = self.kRealString;
NSInteger count = str.length;
NSMutableArray * mutArr = [NSMutableArray array];
if (type == 3 || type == 4) {
if (str.length % type == 0) {
for (int i = 0;i < count / type ; i++) {
NSString * subStr = [str substringWithRange:NSMakeRange(i * type, type)];
[mutArr addObject:subStr];
}
}
}
return [[mutArr copy] componentsJoinedByString:@" "];
}
/// 是否拦截 textfield拼接新输入的数据
/// @param isAdd 是否是输入操作
- (BOOL)kShouldReturn:(BOOL)isAdd{
NSInteger realCount = self.kRealString.length;
if (isAdd) {
if (realCount >= 6) {
if (realCount % 3 == 0) {
return YES;
}else if(realCount % 4 == 0) {
return YES;
}
}
}else{
if (realCount >= 6) {
if (realCount % 3 == 0 || realCount % 4 == 0) {
return YES;
}
}else if (realCount >= 3){
// 正常输入 未达到6位时, 不需要拦截, 该参数在输入达到6位时置成YES, 在删除到3位以下时 置为NO
if (realCount % 3 == 0 && [self.kHasSpace isEqual:@1]) {
return YES;
}
}
}
return NO;
}
@end
2.1 支持3位数字空格分割 - UITextField
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface ZYFTextFieldSpace : UITextField
@end
NS_ASSUME_NONNULL_END
#import "ZYFTextFieldSpace.h"
@interface ZYFTextFieldSpace()<UITextFieldDelegate>
@property (nonatomic, copy) NSString * kRealString; // 当前所有展示数据
@property (nonatomic, copy) NSNumber * kHasSpace; // 输入位数是否触发添加空格
@end
@implementation ZYFTextFieldSpace
//@synthesize text = _text;
-(NSString *)text{
if (self.kRealString) {
return self.kRealString;
}
return @"";
}
- (instancetype)init{
self = [super init];
if (self) {
[self baseConfiguration];
[self setupViews];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
[self baseConfiguration];
[self setupViews];
}
return self;
}
- (void)baseConfiguration{
self.delegate = self;
}
- (void)setupViews{
}
#pragma mark - - - UITextFieldDelegate - - - Start
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
if (![self kDealStringWithSpace:string range:range]) {
return NO;
}
return YES;
}
#pragma mark - - - UITextFieldDelegate - - - End
- (BOOL)kDealStringWithSpace:(NSString *)string range:(NSRange)range{
NSString * realStr = [self.text stringByReplacingCharactersInRange:range withString:string];
if (!self.kRealString) {
self.kRealString = @"";
}
/// 非数字 且 非删除 return false
BOOL isDelete = [string isEqualToString:@""];
self.kRealString = [realStr stringByReplacingOccurrencesOfString:@" " withString:@""];
// 2 符合规则后 更新展示1
[self updateShow:!isDelete range:range string:string];
// 3 部分拦截场景
if ([self kShouldReturn:!isDelete]) {
return NO;
}
return YES;
}
- (void)updateShow:(BOOL)isAdd range:(NSRange)range string:(NSString *)string{
NSInteger realCount = self.kRealString.length;
if (realCount >= 6) {
self.kHasSpace = @1;
NSInteger type = 0;
if (realCount % 3 == 0) {
type = 3;
}else if(realCount % 4 == 0) {
type = 4;
}
if (type > 0) {
NSInteger currentSpaces = [self.text componentsSeparatedByString:@" "].count - 1;
self.text = [self kFilterWithType:type];
NSInteger totalSpace = [self kGetTotalSpace:type] - 1;
currentSpaces = MAX(currentSpaces, 0);
totalSpace = MAX(totalSpace, 0);
NSInteger dif = totalSpace - currentSpaces;
if (isAdd) {
dif ++;
}
NSRange newRange = NSMakeRange(range.location + dif , 0);
if (string.length > 1) {
NSInteger length = self.text.length;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self setSelectedRange:NSMakeRange(length, 0)];
});
}else{
[self setSelectedRange:newRange];
}
}
}else if (realCount >= 3){
if (!isAdd) {
if (realCount % 3 == 0 && [self.kHasSpace integerValue] == 1) {
self.text = [self kFilterWithType:3];
}
}
}else{
if (!isAdd) {
self.kHasSpace = @0;
}
}
}
- (NSInteger)kGetTotalSpace:(NSInteger)type{
NSString * str = self.kRealString;
NSInteger count = str.length;
NSInteger total = 0;
if (type == 3 || type == 4) {
if (str.length % type == 0) {
total = count / type;
}
}
return total;
}
/// 传入位数 , 根据位数动态拼接
/// @param type 位数
- (NSString *)kFilterWithType:(NSInteger)type{
NSString * str = self.kRealString;
NSInteger count = str.length;
NSMutableArray * mutArr = [NSMutableArray array];
if (type == 3 || type == 4) {
if (str.length % type == 0) {
for (int i = 0;i < count / type ; i++) {
NSString * subStr = [str substringWithRange:NSMakeRange(i * type, type)];
[mutArr addObject:subStr];
}
}
}
return [[mutArr copy] componentsJoinedByString:@" "];
}
/// 是否拦截 textfield拼接新输入的数据
/// @param isAdd 是否是输入操作
- (BOOL)kShouldReturn:(BOOL)isAdd{
NSInteger realCount = self.kRealString.length;
if (isAdd) {
if (realCount >= 6) {
if (realCount % 3 == 0) {
return YES;
}else if(realCount % 4 == 0) {
return YES;
}
}
}else{
if (realCount >= 6) {
if (realCount % 3 == 0 || realCount % 4 == 0) {
return YES;
}
}else if (realCount >= 3){
// 正常输入 未达到6位时, 不需要拦截, 该参数在输入达到6位时置成YES, 在删除到3位以下时 置为NO
if (realCount % 3 == 0 && [self.kHasSpace isEqual:@1]) {
return YES;
}
}
}
return NO;
}
@end
3 禁止选中
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface ZYFTextField : UITextField
@property (nonatomic, assign) BOOL isBanSel;
@property (nonatomic, assign) BOOL isBanPerformAction;
@end
NS_ASSUME_NONNULL_END
#import "ZYFTextField.h"
@implementation ZYFTextField
//@synthesize text = _text;
//
//
//-(NSString *)text{
// return _text;
//}
/// 支持 系统item
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender{
if (_isBanPerformAction) {
return NO;
}
// if (action == @selector(paste:))//禁止粘贴
// return NO;
// if (action == @selector(select:))// 禁止选择
// return NO;
// if (action == @selector(selectAll:))// 禁止全选
// return NO;
return [super canPerformAction:action withSender:sender];
}
/// 选中范围
-(NSArray<UITextSelectionRect *> *)selectionRectsForRange:(UITextRange *)range{
NSArray * arr = [super selectionRectsForRange:range];
if (_isBanSel) {
return @[];
}
return arr;
}
/// 光标位置
-(CGRect)caretRectForPosition:(UITextPosition *)position{
if (_isBanSel) {
return CGRectMake(-10, -10, 0, 0);
}
return [super caretRectForPosition:position];
}
@end