如何在UITextView中禁用复制,剪切,选择,全选

时间:2009-09-15 12:00:07

标签: ios objective-c uitextview

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

31 个答案:

答案 0 :(得分:100)

禁用粘贴板操作的最简单方法是创建UITextView的子类,该子类覆盖canPerformAction:withSender:方法以返回NO以执行您不希望允许的操作:

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

另见UIResponder

答案 1 :(得分:67)

子类UITextView并覆盖canBecomeFirstResponder:

- (BOOL)canBecomeFirstResponder {
    return NO;
}

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

答案 2 :(得分:30)

如果您要在应用的所有 UITextView上停用剪切/复制/粘贴,则可以使用类别

@implementation UITextView (DisableCopyPaste)

- (BOOL)canBecomeFirstResponder
{
    return NO;
}

@end

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

答案 3 :(得分:29)

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

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

答案 4 :(得分:21)

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

textField.userInteractionEnabled = NO;

答案 5 :(得分:18)

@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

Swift 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)
    }

}

答案 6 :(得分:15)

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

- (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;
}

答案 7 :(得分:13)

当我在iOS 7上的canPerformAction中返回NO时,我会收到很多这样的错误:

<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.

我的解决方案如下:

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

诀窍是在主队列的下一个循环中隐藏菜单控制器(就在它显示之后)。

答案 8 :(得分:10)

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

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{    
    [UIMenuController sharedMenuController].menuVisible = NO;
    return NO;    
}

答案 9 :(得分:4)

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

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

这使得视图不允许文本选择。对我很有用。

答案 10 :(得分:4)

如果您想用a替换键盘,请说UIPickerinputView(当然工具栏为inputAccesotyView),解决方法可能有帮助...

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

通过执行此操作,您可以点按UITextField并显示可从UIPickerView中选择的选项,此时您的UITextField确实会不对任何触摸事件做出反应(包括触摸和保持剪切,复制和粘贴)。但是,当您关闭UIPickerView时,您必须记住将其设置为YES,但是您无法再次访问UIPickerView

失败的唯一时刻是当用户通过点击并按住UITextView开始时,您第一次看到剪切复制并再次粘贴。这就是您应该始终验证输入的原因。这是我能想到的最容易的。另一种选择是使用UILabel作为只读文字,但是您错过了UITextView的许多强大功能。

答案 11 :(得分:4)

子类UITextView - swift 4.0

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

答案 12 :(得分:2)

这对我有用。确保在textView

上调用resignFirstResponder
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
  [self.textView resignFirstResponder];
  return NO;
}

答案 13 :(得分:2)

我提供了一个有效的答案here来禁用文字选择+放大镜,保持启用的clikable链接 希望有所帮助:

  

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

UIUnselectableTextView.m

-(void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
    if([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]] && gestureRecognizer.delaysTouchesEnded)
    {
        [super addGestureRecognizer:gestureRecognizer];
    }
}

答案 14 :(得分:2)

这可以在故事板(Xcode 6)中轻松完成。只需取消选中“属性”检查器中的“可编辑”和“可选择”。您仍然可以滚动文字视图。enter image description here

答案 15 :(得分:2)

对于 Swift 3 ,它已更改为:

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

答案 16 :(得分:1)

我做到了。在我的UITextView我很容易禁用剪切,复制,选择等选项。

我将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;
        }

    }
}

它对我有用。谢谢。

答案 17 :(得分:1)

如果要禁用window.location.href = "./step1.html" 的弹出窗口,请尝试使用此UITextField方法切换UITextFieldDelegate

isUserInteractionEnabled

答案 18 :(得分: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];
    }

答案 19 :(得分: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)")

    }

答案 20 :(得分:1)

您可以通过取消选中这些框来解决这个问题:

enter image description here

或者你可以这样编程设置:

.column-left{ float: left; width: 20%;}
.column-right{ float: right; width: 20%; visible:false;}
.column-center{ display: inline-block; width: 60%;}

a:link, a:visited {
    background-color: #f44336;
    color: white;
    padding: 14px 25px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
}

a:hover, a:active {
    background-color: red;
}

#test{         margin-left:auto;
               margin-right:auto;
               margin-top:0px;
               margin-bottom:0px;
               border-style:solid;
               border-left:1px;
               border-right:1px;
               border-top:0px;
               border-bottom:1px;
               border-color:#000000;    
               background-color: yellow;
}

答案 21 :(得分: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.

答案 22 :(得分: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)}

答案 23 :(得分:0)

Swift 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)
    }

答案 24 :(得分: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()

答案 25 :(得分:0)

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

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

答案 26 :(得分: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

答案 27 :(得分:0)

UITextView具有两个可以满足您需要的属性: isSelectable isEditable

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

答案 28 :(得分: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
    }

答案 29 :(得分:-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

添加类新类

enter image description here

答案 30 :(得分:-1)

如果您要查找的是iOS> = 13.0版本,则只需在实现UIResponder的任何实施级别使用此扩展名即可:

extension UITextField {
  override var editingInteractionConfiguration: UIEditingInteractionConfiguration {
      return .none
  }
}