背景:

最近在做输入框的需求, 要求:

  • 不能显示选中文本(图中标注的2)
  • 不能弹出气泡(图中标注的1)。

iOS UITextField禁止选中文本(How to disable the selection of a UITextField?)

分析:

  • 不能弹出气泡(图中标注的1)。

这个好做,也是swiftly搜索结果中最多的,canPerformAction根据需要返回NO即可。

  • 不能弹出气泡(图中标注的1)。

这个就不常见中文搜索不到,用英文搜索How to disios模拟器able the selection of a UITextField?,得到一个答案。

- (CGRect)caretRectForPosition:(UITextPosition*) position {
    return CGRectNull;
}
- (NSArray *)selectionRectsForRange:(UITextRange *)range {
    return nil;
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    return NO;
}

UITextField的子类,重写一下ios是什么意思上面的方法,好家伙光标都没了。虽然没有达到理想效果,感觉接近了。 我继续找官方对几个API的注释,找到一个关键的方法,大概就是选中文本swift翻译的绘制矩形框UITextSelectionRect

- (NSArray<UITextSelectionRect *> *)selectionRectsForRange:(UITextRange *)range API_AVAILABLE(ios(6.0));    // Returns an array of UITextSelectionRects

UITextSelios12ectionRect

找到这个关键的类,就看下怎么初始化APP一个新的rect,返回自己想要的就可以ios系统了。

UIKIT_EXTERN API_AVAILABLE(ios(6.0)) NS_SWIFT_UI_ACTOR
@interface UITextSelectionRect : NSObject
@property (nonatomic, readonly) CGRect rect;
@property (nonatomic, readonly) NSWritingDirection writingDirection;
@property (nonatomic, readonly) BOOL containsStart; // Returns YES if the rect contains the start of the selection.
@property (nonatomic, readonly) BOOL containsEnd; // Returns YES if the rect contains the end of the selection.
@property (nonatomic, readonly) BOOL isVertical; // Returns YES if the rect is for vertically oriented text.
@end

这个类没有初始化方法,就得继承一个子类,实现属性的get方法就可以了。 从属性的名swiftkey称可以看到,rect就是ios下载我们想要的。

1. 返回CGRecswiftcode代码查询tZero

- (CGRect)rect{
    return CGRectZero;
}

iOS UITextField禁止选中文本(How to disable the selection of a UITextField?)
问题:

  1. 矩形框确Swift实缩小了,但是在左上角了。

  2. 使用删除键的时候,还是全部删除了。

也就是swift代码说,我们改变了绘制的矩形,但是还是完全选中的。

2. 返回CGRectNuljs输入框l

- (CGRect)rect{
    return CGRectNull;
}

确实没有矩形了,但是使用删除百度输入框键,还是会全部删ios是什么意思除。

最后我们只需要解决最后一个问题:如何取消选中?

如何取消选中?

如何知道当前是否被选中?

// UITextField的子类.m
- (NSArray<UITextSelectionRect *> *)selectionRectsForRange:(UITextRange *)range {
    NSArray *arr = [super selectionRectsForRange:range];
    for (UITextSelectionRect *tmpRect in arr) {
        if (tmpRect.rect.size.width > 0) {
        }
    }
    return arr;
}

apple苹果官网过尝试发现tmpRect.rect.size.width就可以得到选中的宽度,想要自定义选中宽度的就可以动态改变它。 那么tmpRect.rect.size.width > 0就可以知道当前被选中了。

如何取消选中?

看到UITextRswift翻译ange大概就能猜到,可以移动光标来取消选中,那就每次选中的时候,将光标移动到末尾。

// UITextField的子类.m
// CSTextSelectionRect是UITextSelectionRect的子类
- (NSArray<UITextSelectionRect *> *)selectionRectsForRange:(UITextRange *)range {
    NSArray *arr = [super selectionRectsForRange:range];
    for (UITextSelectionRect *tmpRect in arr) {
        if (tmpRect.rect.size.width > 0) {
            UITextPosition *endPosition = [self endOfDocument];
            UITextRange *textRange =[self textRangeFromPosition:endPosition
                                                     toPosition:endPosition];
            [self setSelectedTextRange:textRange];
            return @[CSTextSelectionRect.new];
        }
    }
    return arr;
}

总结:

  1. 新建UITextField一个子类,重写selectionRectsForRange方法。(实现没有选中的显示效果)
  2. 新建UITextSelectionRect一个子类,重写rect方法,返回CGRectNull。(实现没有选中的显示效果)
  3. 选中swiftly的时候,ios12移动光标在末尾。(实现真正没有选中)