如何禁用 UITextField 的选择?

Posted

技术标签:

【中文标题】如何禁用 UITextField 的选择?【英文标题】:How to disable the selection of a UITextField? 【发布时间】:2015-09-29 14:30:34 【问题描述】:

我使用 UITextField 是因为我想要一个自定义的弹出式键盘。但是,我不希望用户能够更改插入点或访问复制、粘贴菜单。

我发现了两个有用的 *** 问题,并尝试实现它们:

Disable Magnifying Glass in UITextField

(iPhone) How to handle touches on a UITextView?

我通过子类化 UITextField 并实现该方法删除了菜单:

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender 
    return NO;

但是,当用户双击该字段时,我未能阻止该字段被选中:

我尝试删除我认为对选择行为负责的手势识别器,但没有成功。那么我做错了什么?

@property (nonatomic, strong) MinimalTextField *inputText;
...
@synthesize inputText;
...

- (void)viewDidAppear:(BOOL)animated

    [super viewDidAppear: animated];    
    NSLog(@"%ld gestureRecognizers initially ", (long)inputText.gestureRecognizers.count);

    for (UIGestureRecognizer *gestureRecognizer in inputText.gestureRecognizers)         
        if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) 
            UITapGestureRecognizer *tapGestureRecognizer = (UITapGestureRecognizer *)gestureRecognizer;
            if ([tapGestureRecognizer numberOfTapsRequired] == 2) 
                NSLog(@"found & removed: %@", tapGestureRecognizer);
                [inputText removeGestureRecognizer:tapGestureRecognizer];
            
        
        if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) 
            UILongPressGestureRecognizer *longPressGestureRecognizer = (UILongPressGestureRecognizer *)gestureRecognizer;
            NSLog(@"found & removed: %@", longPressGestureRecognizer);
            [inputText removeGestureRecognizer:longPressGestureRecognizer];
        
    

    NSLog(@"%ld gestureRecognizers remaining", (long)inputText.gestureRecognizers.count);

    for (UIGestureRecognizer *gestureRecognizer in inputText.gestureRecognizers) 
        NSLog(@"gestureRecognizer: %@", gestureRecognizer);
    

此代码产生以下输出,所以我知道它正在工作,但它无法影响双击操作。

7 gestureRecognizers initially 
found & removed: <UITextTapRecognizer: 0x7ff6086571f0; state = Possible; delaysTouchesEnded = NO; view = <MinimalTextField 0x7ff608414b10>; target= <(action=oneFingerDoubleTap:, target=<UITextInteractionAssistant 0x7ff608652de0>)>; numberOfTapsRequired = 2>
found & removed: <UILongPressGestureRecognizer: 0x7ff608658180; state = Possible; delaysTouchesEnded = NO; view = <MinimalTextField 0x7ff608414b10>; target= <(action=twoFingerRangedSelectGesture:, target=<UITextInteractionAssistant 0x7ff608652de0>)>>
found & removed: <UIVariableDelayLoupeGesture: 0x7ff608658a40; state = Possible; delaysTouchesEnded = NO; view = <MinimalTextField 0x7ff608414b10>; target= <(action=loupeGesture:, target=<UITextInteractionAssistant 0x7ff608652de0>)>>

4 gestureRecognizers remaining
gestureRecognizer: <UITextTapRecognizer: 0x7ff608653960; state = Possible; delaysTouchesEnded = NO; view = <MinimalTextField 0x7ff608414b10>; target= <(action=oneFingerTripleTap:, target=<UITextInteractionAssistant 0x7ff608652de0>)>; numberOfTapsRequired = 3>
gestureRecognizer: <UITextTapRecognizer: 0x7ff6086576e0; state = Possible; delaysTouchesEnded = NO; view = <MinimalTextField 0x7ff608414b10>; target= <(action=twoFingerSingleTap:, target=<UITextInteractionAssistant 0x7ff608652de0>)>; numberOfTouchesRequired = 2>
gestureRecognizer: <UITapAndAHalfRecognizer: 0x7ff608657c70; state = Possible; view = <MinimalTextField 0x7ff608414b10>; target= <(action=tapAndAHalf:, target=<UITextInteractionAssistant 0x7ff608652de0>)>>
gestureRecognizer: <UITextTapRecognizer: 0x7ff6086585f0; state = Possible; delaysTouchesEnded = NO; view = <MinimalTextField 0x7ff608414b10>; target= <(action=oneFingerTap:, target=<UITextInteractionAssistant 0x7ff608652de0>)>>

我什至尝试将以下代码添加到我的 UITextField 子类中:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer

    NSLog(@"Gesture should begin");
    if ([gestureRecognizer isKindOfClass:[UIRotationGestureRecognizer class]])
        NSLog(@"rotate");
    if ([gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]])
        NSLog(@"pinch");
    if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) 
        NSLog(@"tap");
        NSLog(@"numberOfTouches: %ld", (long)gestureRecognizer.numberOfTouches);
    
    if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]])
        NSLog(@"pan");
    if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]])
        NSLog(@"long");
    if ([gestureRecognizer isKindOfClass:[UISwipeGestureRecognizer class]])
        NSLog(@"swipe");
    return YES;

但是,没有可用的属性gestureRecognizer.numberOfTaps,所以我怎么知道它被点击的频率。

【问题讨论】:

【参考方案1】:

我发现这篇有用的文章为我解决了这个问题:https://www.transpire.com/insights/blog/disabling-caret-text-entry-uitextfields/

您需要将以下覆盖添加到您的 UITextField 子类(它们基本上禁用 UIMenuController 并隐藏选择和插入符号):

目标-C

- (CGRect)caretRectForPosition:(UITextPosition*) position 
    return CGRectNull;


- (NSArray *)selectionRectsForRange:(UITextRange *)range 
    return nil;


- (BOOL)canPerformAction:(SEL)action withSender:(id)sender 
    return NO;

斯威夫特

override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool 
    false


override func selectionRects(for range: UITextRange) -> [UITextSelectionRect] 
    []


override func caretRect(for position: UITextPosition) -> CGRect 
    .null

【讨论】:

我找到的唯一合适的解决方案,干得好。当您第二次触摸文本字段时,我仍然看到一些小故障,开始时 0 字符上的选择出现在某些帧中.. 仍然是最好的解决方案。 ? @itMaxence 这似乎为我修复了这个错误:将caretRect 设置为.null 而不是.zero @MichaelEllis 感谢您的建议。我批准了。我不知道.null 存在! :D 我假设通过用CGRectNull 替换CGRectZero 可以对Objective-C 版本说同样的话。我还没有测试过。 当我从 caretRect(for position: UITextPosition) 返回 .null 时,我在 Xcode 日志中有这个:_NSLayoutTreeLineFragmentRectForGlyphAtIndex invalid glyph index 9223372036854775807。不知道这算不算大事? ?‍♂️ @bob 听起来像是零引用错误警告消息日志输出。 LayoutTree -LineFragmentRect - ForGlyph AtIndex,布局树中的线片段矩形有一个零插入符号位置。可能没什么好担心的,我没有任何问题,也没有我的 ios 15.3 和 xcode 13.2.1 的测试人员和用户【参考方案2】:

UITextView 有一个属性selectable 可以帮助你

【讨论】:

没错,我可能最终会使用 UITextView。不幸的是,我写错了这个问题的标题,我刚刚修改了它。 让我重新表述我的回答。我仍然有同样的问题,我不知道如何禁用 UITextField 的选择。在我第一次发布的原始问题中,我错误地写了 UITextView 而不是 UITextField,我对其进行了编辑以纠正这个错误。我需要在我的代码中使用 UITextField,不幸的是它没有可选的属性。 不知道怎么做,但是如果你通过在 UITextField 上放置一个调用 [textField becomeFirstResponder];on 它的操作方法的按钮来禁用对 UITextField 的所有点击会怎样

以上是关于如何禁用 UITextField 的选择?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Xamarin IOS 自定义渲染器中单击 UITextField Rightview 打开 UIPickerView

在 UITextField 中禁用“定义”

占位符右对齐的 UITextField 不能正确向右移动

用户可以选择禁用用户交互的UITextField

UITextField如何禁用粘贴? [复制]

如何禁用 UITextField 的编辑属性? [复制]