The UITextView
\'s Copy, Cut, Select, Select All functionality is shown by default when I press down on the screen. But, in my project the UITextField
is only read only. I do not require this functionality. Please tell me how to disable this feature.
问题:
回答1:
The easiest way to disable pasteboard operations is to create a subclass of UITextView
that overrides the canPerformAction:withSender:
method to return NO
for actions that you don\'t want to allow:
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
if (action == @selector(paste:))
return NO;
return [super canPerformAction:action withSender:sender];
}
Also see UIResponder
回答2:
Subclass UITextView and overwrite canBecomeFirstResponder:
- (BOOL)canBecomeFirstResponder {
return NO;
}
Note, that this only applies for non-editable UITextViews! Haven\'t tested it on editable ones...
回答3:
If you want to disable cut/copy/paste on all UITextView
of your application you can use a category with :
@implementation UITextView (DisableCopyPaste)
- (BOOL)canBecomeFirstResponder
{
return NO;
}
@end
It saves a subclassing... :-)
回答4:
This was the best working solution for me:
UIView *overlay = [[UIView alloc] init];
[overlay setFrame:CGRectMake(0, 0, myTextView.contentSize.width, myTextView.contentSize.height)];
[myTextView addSubview:overlay];
[overlay release];
from: https://stackoverflow.com/a/5704584/1293949
回答5:
If you don\'t need UITextView to scroll, then the simplest solution that doesn\'t involve sub-classing is to simply disable user interaction for the text view:
textField.userInteractionEnabled = NO;
回答6:
The easiest way is to create a subclass of UITextView that overrides the canPerformAction: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:
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).
回答8:
@rpetrich answer worked for me. I\'m posting the expanded code in case it saves someone some time.
In my case I want no popup whatsoever, but I do want the UITextField to be able to become first responder.
Unfortunately, you still get the magnifier popup when you tap and hold the textfield.
@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)
}
}
回答9:
This is the easiest way to disable the entire Select/Copy/Paste Menu in a UITextView
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
[UIMenuController sharedMenuController].menuVisible = NO;
return NO;
}
回答10:
Since iOS 7 there is a property on UITextView:
@property(nonatomic,getter=isSelectable) BOOL selectable;
This keeps a view from allowing text selections. Works great for me.
回答11:
If you are looking to replace the keyboard with a, let\'s say, UIPicker
as the inputView
(with of course a toolbar as an inputAccesotyView
), then this workaround might help...
- Implement
textFieldShouldBeginEditing:
- inside put
textField.userInteractionEnabled = NO;
- Then when you are about to close the
UIPickerView
, set it to YES.
By doing this, you\'d be able to tap on the UITextField
and show the options to choose from the UIPickerView
, at this time your UITextField
would, indeed, not react to any touch event (this includes touch and hold for cut, copy and paste). However, you would have to remember to set it back to YES when you are closing your UIPickerView
however you won\'t be able to access your UIPickerView
again.
The only moment when it fails is when the user starts by tapping and holding the UITextView
, then you\'d see cut copy and paste again for the first time. This is why you should always validate your inputs. This is the easiest I can think of. The other option was to use a UILabel
for read-only text but you miss a lot of great functionality from UITextView
.
回答12:
Subclass UITextView - swift 4.0
override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
回答13:
I provided a working answer here to disable text selection + magnifier, keeping enabled clikable links Hope that helps :
After quite a long time trying, I managed to stop text selection, magnifying, and keeping data detection (links clickable etc) by overriding addGestureRecognizer on a UITextView subclass allowing only UILongPressGestureRecognizer delaying touch ending:
UIUnselectableTextView.m
-(void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
if([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]] && gestureRecognizer.delaysTouchesEnded)
{
[super addGestureRecognizer:gestureRecognizer];
}
}
回答14:
This can be done easily in storyboard (Xcode 6). Just uncheck Editable and Selectable in Attributes Inspector. You can still scroll the text view.
回答15:
For Swift 3 it\'s changed to:
override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
回答16:
This worked for me. Make sure you are calling resignFirstResponder on the textView
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
[self.textView resignFirstResponder];
return NO;
}
回答17:
I have done it. On my UITextView
I have disabled cut, copy, select, etc. option very easily.
I placed a UIView
at the same place where i had placed the UITextView
, but on self.view
and added a touchDelegate
method as follows:
(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;
}
}
}
and it worked for me. Thank you.
回答18:
Swift
textView.selectable = false // disable text selection (and thus copy/paste/etc)
Related
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.
回答19:
You can fix this in your storyboard by unchecking these box:
Or you can set programatically like so:
textView.selectable = false
textView.editable = false
回答20:
This method will completely disable the Select, Select All, Paste menu. If you still get some other action, then just add that to the if condition as below.
- (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];
}
回答21:
You can just create category like this:
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
回答22:
Subclassing UITextView
and overriding - (void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
is another possibility to disable unwanted actions.
Use the class of the gestureRecognizer
-object to decide if the action should be added or not.
回答23:
(SWIFT) If you want just a basic text field with none of the menu options or magnifying glass then create a subclass of UITextField returning false to gestureRecognizerShouldBegin:
class TextFieldBasic: UITextField {
override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
}
This will bypass all the touch functionality on the text field but still allow you to use the popup keyboard to add / remove characters.
If you are using storyboard just assign the newly created class to the text field or if you are creating a text field programatically:
var basicTextField = TextFieldBasic()
basic = basicTextField(frame: CGRectMake(10, 100, 100,35))
basic.backgroundColor = UIColor.redColor()
self.view.addSubview(basic)
basic.becomeFirstResponder()
回答24:
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)}
回答25:
Swift 3
In order to do this, you need to subclass your UITextView and put this method.
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)
}
回答26:
If you want to add a custom option to your UITextView but disable the existing functions this is how you do it on Swift 3 :
To disable the copy, paste, cut funcionality create a subclass and override the following:
override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
On the ViewController you have your CustomTextView add the following to add your options:
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)\")
}
回答27:
If want to disable popup for UITextField
then try this UITextFieldDelegate
method to toggle isUserInteractionEnabled
.
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
textField.isUserInteractionEnabled = false
return true
}
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
textField.isUserInteractionEnabled = true
return true
}
回答28:
Use func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { retrun bool }
in place of 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
}
}
Create a new class with name StopPasteAction.swift
import UIKit
class StopPasteAction: UITextField {
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
}
Add the class new class with you current TextField