112

UITextView我在屏幕上按下时,默认情况下会显示 的复制、剪切、选择、全选功能。但是,在我的项目中,UITextField它是只读的。我不需要这个功能。请告诉我如何禁用此功能。

4

31 回答 31

110

禁用粘贴板操作的最简单方法是创建一个子类,UITextView该子类覆盖为您不想允许的操作canPerformAction:withSender:返回的方法:NO

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    if (action == @selector(paste:))
        return NO;
    return [super canPerformAction:action withSender:sender];
}

另见UIResponder

于 2009-09-15T19:58:16.607 回答
67

继承 UITextView 并覆盖 canBecomeFirstResponder:

- (BOOL)canBecomeFirstResponder {
    return NO;
}

请注意,这仅适用于不可编辑的 UITextViews!还没有在可编辑的上测试它...

于 2010-08-06T19:46:24.807 回答
30

这对我来说是最好的工作解决方案:

UIView *overlay = [[UIView alloc] init];  
[overlay setFrame:CGRectMake(0, 0, myTextView.contentSize.width, myTextView.contentSize.height)];  
[myTextView addSubview:overlay];  
[overlay release];

来自:https ://stackoverflow.com/a/5704584/1293949

于 2012-03-26T21:46:51.087 回答
28

如果您想在所有 UITextView应用程序上禁用剪切/复制/粘贴,您可以使用以下类别

@implementation UITextView (DisableCopyPaste)

- (BOOL)canBecomeFirstResponder
{
    return NO;
}

@end

它保存了一个子类... :-)

于 2011-11-04T17:39:13.437 回答
25

@rpetrich 答案对我有用。我正在发布扩展代码,以防它节省一些时间。

就我而言,我不希望任何弹出窗口,但我确实希望 UITextField 能够成为第一响应者。

不幸的是,当您点击并按住文本字段时,您仍然会看到放大镜弹出窗口。

@interface NoSelectTextField : UITextField

@end

@implementation NoSelectTextField

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    if (action == @selector(paste:) ||
        action == @selector(cut:) ||
        action == @selector(copy:) ||
        action == @selector(select:) ||
        action == @selector(selectAll:) ||
        action == @selector(delete:) ||
        action == @selector(makeTextWritingDirectionLeftToRight:) ||
        action == @selector(makeTextWritingDirectionRightToLeft:) ||
        action == @selector(toggleBoldface:) ||
        action == @selector(toggleItalics:) ||
        action == @selector(toggleUnderline:)
        ) {
            return NO;
    }
    return [super canPerformAction:action withSender:sender];
}

@end

斯威夫特 4

class NoSelectTextField: UITextField {

    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        if action == #selector(paste(_:)) ||
            action == #selector(cut(_:)) ||
            action == #selector(copy(_:)) ||
            action == #selector(select(_:)) ||
            action == #selector(selectAll(_:)) ||
            action == #selector(delete(_:)) ||
            action == #selector(makeTextWritingDirectionLeftToRight(_:)) ||
            action == #selector(makeTextWritingDirectionRightToLeft(_:)) ||
            action == #selector(toggleBoldface(_:)) ||
            action == #selector(toggleItalics(_:)) ||
            action == #selector(toggleUnderline(_:)) {
            return false
        }
        return super.canPerformAction(action, withSender: sender)
    }

}
于 2014-11-20T19:02:57.260 回答
20

如果您不需要 UITextView 滚动,那么不涉及子类化的最简单解决方案是简单地禁用文本视图的用户交互:

textField.userInteractionEnabled = NO;
于 2010-11-09T15:46:07.233 回答
15

最简单的方法是创建一个覆盖 canPerformAction:withSender 的 UITextView 的子类:

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender    
{    
     [UIMenuController sharedMenuController].menuVisible = NO;  //do not display the menu
     [self resignFirstResponder];                      //do not allow the user to selected anything
     return NO;
}
于 2010-04-24T06:13:22.050 回答
13

When I return NO in the canPerformAction on iOS 7 I will get a lot of errors like this:

<Error>: CGContextSetFillColorWithColor: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.

My solution is the following:

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        [[UIMenuController sharedMenuController] setMenuVisible:NO animated:NO];
    }];
    return [super canPerformAction:action withSender:sender];
}

The trick is to hide the menu controller in the next cycle on the main queue (just after it is displayed).

于 2014-03-04T12:34:44.803 回答
9

这是在 UITextView 中禁用整个选择/复制/粘贴菜单的最简单方法

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{    
    [UIMenuController sharedMenuController].menuVisible = NO;
    return NO;    
}
于 2009-11-10T18:54:53.420 回答
6

如果您想禁用弹出窗口,请UITextField尝试使用此UITextFieldDelegate方法切换isUserInteractionEnabled

func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
    textField.isUserInteractionEnabled = false
    return true
}
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
    textField.isUserInteractionEnabled = true
    return true
}
于 2018-09-10T09:12:00.343 回答
5

如果您想用一个替换键盘,比如说,UIPicker作为inputView(当然工具栏作为一个inputAccesotyView),那么这个解决方法可能会有所帮助......

  • 实施textFieldShouldBeginEditing:
  • 内放textField.userInteractionEnabled = NO;
  • 然后,当您要关闭 时UIPickerView,将其设置为 YES。

通过这样做,您可以点击UITextField并显示可供选择的选项UIPickerView,此时您UITextField实际上不会对任何触摸事件做出反应(这包括用于剪切、复制和粘贴的触摸并按住)。但是,您必须记住在关闭时将其设置回 YES,UIPickerView但是您将无法UIPickerView再次访问您的。

它失败的唯一时刻是当用户开始点击并按住 时UITextView,您会第一次看到剪切复制和粘贴。这就是为什么您应该始终验证您的输入的原因。这是我能想到的最简单的。另一种选择是使用UILabel只读文本,但你错过了很多很棒的功能UITextView

于 2014-05-29T00:23:07.370 回答
4

从 iOS 7 开始,UITextView 上有一个属性:

 @property(nonatomic,getter=isSelectable) BOOL selectable;

这可以防止视图允许文本选择。对我很有用。

于 2014-02-23T17:16:29.940 回答
4

子类 UITextView - swift 4.0

     override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        return false
    }
于 2018-04-03T11:51:14.683 回答
3

这对我有用。确保您在 textView 上调用 resignFirstResponder

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
  [self.textView resignFirstResponder];
  return NO;
}
于 2013-03-24T11:05:33.550 回答
3

这可以在故事板(Xcode 6)中轻松完成。只需取消选中 Attributes Inspector 中的 Editable 和 Selectable。您仍然可以滚动文本视图。在此处输入图像描述

于 2015-08-13T02:31:33.067 回答
2

我已经做了。在我UITextView的身上,我很容易禁用了剪切、复制、选择等选项。

我将 a 放置UIView在放置 , 的同一位置UITextView,但self.view添加了一个touchDelegate方法,如下所示:

(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{
    UITouch *scrollTouch=[touches anyObject];
    if(scrollTouch.view.tag==1)
    {
        NSLog(@"viewTouched");
        if(scrollTouch.tapCount==1)
            [textView1 becomeFirstResponder];
        else if(scrollTouch.tapCount==2)
        {
            NSLog(@"double touch");
            return;
        }

    }
}

它对我有用。谢谢你。

于 2009-11-09T19:25:17.413 回答
2

我在这里提供了一个可行的答案禁用文本选择+放大镜,保持启用的可点击链接希望有所帮助:

经过很长时间的尝试,我设法通过覆盖 UITextView 子类上的 addGestureRecognizer 来停止文本选择、放大和保持数据检测(链接可点击等),只允许 UILongPressGestureRecognizer 延迟触摸结束:

UIUnselectableTextView.m

-(void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
    if([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]] && gestureRecognizer.delaysTouchesEnded)
    {
        [super addGestureRecognizer:gestureRecognizer];
    }
}
于 2015-03-09T10:51:28.613 回答
2

您可以通过取消选中以下框在情节提要中解决此问题:

在此处输入图像描述

或者您可以像这样以编程方式设置:

textView.selectable = false
textView.editable = false
于 2016-02-06T10:30:25.983 回答
2

对于Swift 3,它改为:

override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
    return false
}
于 2016-08-18T09:53:04.680 回答
1

如果您想向 UITextView 添加自定义选项但禁用现有功能,这就是您在Swift 3上执行此操作的方式:

要禁用复制、粘贴、剪切功能,请创建一个子类并覆盖以下内容:

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

在 ViewController 上,您的 CustomTextView 添加以下内容以添加您的选项:

  let selectText = UIMenuItem(title: "Select", action: #selector(ViewController.selected))

    func selected() {

    if let selectedRange = textView.selectedTextRange, let 
     selectedText = textView.text(in: selectedRange) {

     }


    print("User selected text: \(selectedText)")

    }
于 2017-09-06T06:31:43.240 回答
1

此方法将完全禁用选择、全选、粘贴菜单。如果您仍然获得其他操作,则只需将其添加到 if 条件中,如下所示。

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender // This is to disable select / copy / select all / paste menu
    {
        if (action == @selector(copy:) || action == @selector(selectAll:) || action == @selector(select:) || action == @selector(paste:))
            return NO;
        return [super canPerformAction:action withSender:sender];
    }
于 2018-02-23T06:00:09.543 回答
1

如果您正在寻找 iOS >=13.0 版本,您可以简单地在任何级别的实现中使用此扩展,直至 UIResponder:

extension UITextField {
  override var editingInteractionConfiguration: UIEditingInteractionConfiguration {
      return .none
  }
}
于 2020-09-17T10:02:02.723 回答
1

迅速

textView.selectable = false // disable text selection (and thus copy/paste/etc)

有关的

textView.editable = false // text cannot be changed but can still be selected and copied
textView.userInteractionEnabled = false // disables all interaction, including scrolling, clicking on links, etc.
于 2015-09-26T07:23:16.087 回答
0

子类化UITextView和覆盖- (void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer是禁用不需要的操作的另一种可能性。

使用gestureRecognizer-object 的类来决定是否应该添加操作。

于 2014-06-24T12:57:41.480 回答
0

您可以像这样创建类别:

UITextView+Selectable.h

@interface UITextView (Selectable)

@property (nonatomic, assign, getter = isTextSelectable) bool textSelectable;

@end

UITextView+Selectable.m

#import "UITextView+Selectable.h"

#import <objc/runtime.h>

#define TEXT_SELECTABLE_PROPERTY_KEY @"textSelectablePropertyKey"

@implementation UITextView (Selectable)

@dynamic textSelectable;

-(void)setTextSelectable:(bool)textSelectable {
    objc_setAssociatedObject(self, TEXT_SELECTABLE_PROPERTY_KEY, [NSNumber numberWithBool:textSelectable], OBJC_ASSOCIATION_ASSIGN);
}

-(bool)isTextSelectable {
    return [objc_getAssociatedObject(self, TEXT_SELECTABLE_PROPERTY_KEY) boolValue];
}

-(bool)canBecomeFirstResponder {
    return [self isTextSelectable];
}

@end
于 2014-05-03T08:43:03.780 回答
0

请查找示例代码以供参考:

 override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        if action == #selector(copy(_:)) || action == #selector(paste(_:)) || action == #selector(UIResponderStandardEditActions.paste(_:)) ||
            action == #selector(replace(_:withText:)) ||
            action == #selector(UIResponderStandardEditActions.cut(_:)) ||
        action == #selector(UIResponderStandardEditActions.select(_:)) ||
        action == #selector(UIResponderStandardEditActions.selectAll(_:)) ||
        action == #selector(UIResponderStandardEditActions.delete(_:)) ||
        action == #selector(UIResponderStandardEditActions.makeTextWritingDirectionLeftToRight(_:)) ||
        action == #selector(UIResponderStandardEditActions.makeTextWritingDirectionRightToLeft(_:)) ||
        action == #selector(UIResponderStandardEditActions.toggleBoldface(_:)) ||
        action == #selector(UIResponderStandardEditActions.toggleItalics(_:)) ||
        action == #selector(UIResponderStandardEditActions.toggleUnderline(_:)) ||
        action == #selector(UIResponderStandardEditActions.increaseSize(_:)) ||
        action == #selector(UIResponderStandardEditActions.decreaseSize(_:))

       {
            return false
        }

        return true
    }
于 2019-12-30T13:07:56.047 回答
0

斯威夫特 3

为了做到这一点,你需要继承你的 UITextView 并放置这个方法。

override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        if (action == #selector(copy(_:))) {
            return false
        }

        if (action == #selector(cut(_:))) {
            return false
        }

        if (action == #selector(paste(_:))) {
            return false
        }

        return super.canPerformAction(action, withSender: sender)
    }
于 2017-05-25T12:00:47.907 回答
0

UITextView 有两个属性可以满足您的需求:isSelectableisEditable

将 isEditable 设置为 false 将避免用户编辑文本,将isSelectable设置为 false 将避免用户在 textView 中选择文本,因此这将阻止显示操作菜单。

于 2019-08-06T12:31:48.497 回答
0

(SWIFT)如果您只想要一个没有菜单选项或放大镜的基本文本字段,则创建一个 UITextField 的子类,将 false 返回到 gestureRecognizerShouldBegin:

class TextFieldBasic: UITextField {
    override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {

        return false
    }
}

这将绕过文本字段上的所有触摸功能,但仍允许您使用弹出键盘添加/删除字符。

如果您使用情节提要,只需将新创建的类分配给文本字段,或者如果您正在以编程方式创建文本字段:

var basicTextField = TextFieldBasic()
basic = basicTextField(frame: CGRectMake(10, 100, 100,35))
basic.backgroundColor = UIColor.redColor()
self.view.addSubview(basic)

basic.becomeFirstResponder()
于 2015-09-24T12:59:57.820 回答
0
override func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool 
{
    NSOperationQueue .mainQueue().addOperationWithBlock({ () -> Void in   

        [UIMenuController .sharedMenuController() .setMenuVisible(false, animated: true)]

    })
    return super.canPerformAction(action, withSender: sender)}
于 2016-01-06T12:59:25.473 回答
-1

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { retrun bool }代替textFieldShouldBeginEditing. _

class ViewController: UIViewController , UITextFieldDelegate {

    @IBOutlet weak var textField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        //Show date picker
        let datePicker = UIDatePicker()
        datePicker.datePickerMode = UIDatePickerMode.date
        textField.tag = 1
        textField.inputView = datePicker
    }

    func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
        if textField.tag == 1 {
            textField.text = ""
            return false
        }

        return true
    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if textField.tag == 1 {
            textField.text = ""
            return false
        }

        return true
    }
}

创建一个名为 StopPasteAction.swift 的新类

import UIKit

class StopPasteAction: UITextField {

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

使用当前的 TextField 添加类新类

在此处输入图像描述

于 2017-09-05T02:38:27.063 回答