美文网首页
UITextField 支持内容滚动、3位数字间空格分割、禁止选

UITextField 支持内容滚动、3位数字间空格分割、禁止选

作者: 简繁之间_来去自然 | 来源:发表于2022-10-23 10:19 被阅读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
    
    

    相关文章

      网友评论

          本文标题:UITextField 支持内容滚动、3位数字间空格分割、禁止选

          本文链接:https://www.haomeiwen.com/subject/sltgzrtx.html