UITextView에서 복사, 잘라 내기, 선택, 모두 선택을 비활성화하는 방법


110

UITextView의 복사, 잘라 내기, 선택은 모두 선택 기능은 I가 화면에 눌러 기본적으로 표시됩니다. 그러나 내 프로젝트에서는 UITextField읽기 전용입니다. 이 기능이 필요하지 않습니다. 이 기능을 비활성화하는 방법을 알려주십시오.


3
place [UIMenuController sharedMenuController] .menuVisible = 아니오; in-(BOOL) canPerformAction : (SEL) action withSender : (id) sender 메서드.
ravoorinandan

답변:


108

대지 작업을 비활성화하는 가장 쉬운 방법은 허용하지 않으려는 작업에 대해 반환 UITextViewcanPerformAction:withSender:메서드를 재정의 하는의 하위 클래스를 만드는 것입니다 NO.

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

UIResponder 참조


1
@rpetrichm, 솔루션을 사용했습니다. 복사 / 붙여 넣기 / 잘라 내기 / 선택 / 선택 모든 옵션이 비활성화되어 있지만 계속 교체 ... | BIU | 옵션 정의. 전체 메뉴를 비활성화하고 싶습니다.
Ameet Dhas 2014 년

3
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender { return NO; }-모든 옵션 차단
이슬람 Q.

훌륭하지만 UISearchBar에 대해이 작업을 수행하는 방법을 모르겠습니다. 내부에 텍스트 필드도 있기 때문에 UISearchBar의 하위 클래스의 메서드를 덮어 쓸 수 있다고 생각했지만 불행히도 작동하지 않습니다. 이것에 대한 아이디어가 있습니까?
borchero

나는 많은 컨트롤을 가지고 있습니다. 하나의 컨트롤에만 복사 붙여 넣기를 허용하는 방법은 무엇입니까?
Gaucho

이 솔루션은 여러 곳에서 제안 된 것을 보았지만 UITextView에서는 작동하지 않습니다. 누구든지 이것을 수행하는 방법을 알아 냈습니까?
Pigpocket 2018-06-24

67

UITextView 하위 클래스 및 canBecomeFirstResponder 덮어 쓰기 :

- (BOOL)canBecomeFirstResponder {
    return NO;
}

이것은 편집 불가능한 UITextView에만 적용된다는 점에 유의하십시오! 편집 가능한 항목에서 테스트하지 않았습니다 ...


방법이 더 나은 선택 이라고 생각 return NO;합니다 - (BOOL)canPerformAction:(SEL)action withSender:(id)sender.
이슬람 Q.

29

모든 UITextView 응용 프로그램 에서 잘라 내기 / 복사 / 붙여 넣기를 비활성화 하려면 다음 과 함께 범주 를 사용할 수 있습니다 .

@implementation UITextView (DisableCopyPaste)

- (BOOL)canBecomeFirstResponder
{
    return NO;
}

@end

그것은 서브 클래 싱을 저장합니다 ... :-)


3
이 동작이 필요한 곳에 /, 파일에만 이것을 넣을 수도 있습니다.
markus_p 2010

4
이것은 부작용으로 만 작동하며 UITextView예를 들어 편집 가능하고 터치를 얻을 때 예상대로 작동 하지 않도록합니다 . 무시할 것이 많다 canPerformAction:withSender:. 그것이 프로토콜의 목적입니다.
jdc 2013 년

16
범주를 사용하여 메서드를 안전하게 재정의 할 수 없습니다. 이것은 정의되지 않은 동작입니다. 메서드를 안전하게 재정의하려면 하위 클래스를 만들어야합니다.
Rob Napier

2
참고 : 이는 애플리케이션의 모든 UITextView에 적용됩니다. 대부분의 경우 이상적이지 않습니다.
bbrame 2013-08-22

2
또한 Apple 은 이에 대해 다음과 같이 권고합니다 . "범주에 선언 된 메서드의 이름이 원래 클래스의 메서드와 같거나 같은 클래스 (또는 수퍼 클래스)의 다른 범주에있는 메서드와 같으면 동작은 다음과 같습니다. 런타임에 어떤 메소드 구현이 사용되는지 정의되지 않았습니다. [그리고] 카테고리를 사용하여 표준 Cocoa 또는 Cocoa Touch 클래스에 메소드를 추가 할 때 문제가 발생할 수 있습니다. "
Rob

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


3
여기에 서브 클래 싱이 없습니다!
Martin Reichl 2013 년

7
나는 여기서 덕트 테이프와 나르는 와이어 접근 방식을 좋아합니다. 나는 다시 일하면 좋겠지 : 대신, 여기에 골드 스타 인 : i.imgur.com/EXLFt1Z.jpg
JDC

22

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

}

1
이것에 대한 빠른 버전도 게시하십시오. 감사합니다.
Salman Khakwani

@ 핀치 : tnx. iOS 12.1.3에서 여전히 물을 보유하고 있습니다.
YvesLeBorg

20

스크롤하는 데 UITextView가 필요하지 않은 경우 하위 클래스를 포함하지 않는 가장 간단한 솔루션은 단순히 텍스트보기에 대한 사용자 상호 작용을 비활성화하는 것입니다.

textField.userInteractionEnabled = NO;

2
이것은 텍스트보기에있는 경우 링크 등을 두드리는 것을 제거합니다. 이것은 선택 / 복사 / 붙여 넣기를 숨기고 자하는 경우에 좋은 해결책은 아니지만, 일정 수준의 상호 작용을 활성화 한 상태로 유지합니다.
barfoon

3
글쎄, 나는 그것이 명백 할 것이라고 생각했을 것이다.
Luke Redpath 2012

게임에서 그림의 레이블로 텍스트 필드를 사용하고 있으며 돋보기가 표시되는 것을 원하지 않으며 텍스트를 복사 할 이유가 없습니다. 이것은 나를 위해 잘 작동합니다. UIWebView에서 스타일이 지정된 텍스트를 사용하고 있으며 동일한 줄도 거기에서 작동합니다.
JScarry 2013

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

이것은 텍스트 만 입력 할 수있는 최상의 솔루션이며 텍스트 필드를 탭해도 더 이상 '차단'되지 않습니다. 이것은 OP가 원하는 것을 수행합니다.
hlfcoding 2013 년

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

트릭은 메인 대기열의 다음주기에서 메뉴 컨트롤러를 숨기는 것입니다 (표시된 직후).


정말 좋아요. 유일한 문제는 2 개의 textview와 1 개의 textField가 있고 textView 필드에만 복사하여 붙여 넣기를 피하고 싶다는 것입니다. canPerformAction을 호출 한 사람을 식별하는 방법은 무엇입니까? 발신자 변수는 UIMenuController입니다
Gaucho

1
UITextField (또는 UITextView)의 하위 클래스에서 작동합니다. 만든 하위 클래스를 사용하지 않으면 효과가 없습니다. 예를 들어 TextFieldWithoutCopyPaste를 만들고 복사 붙여 넣기 기능을 원하지 않는 곳에 사용했습니다.
Adam Wallner

네 말이 맞아요. 하지만 필자의 경우에는 textView에 canPerformAction을 사용하기위한 하위 클래스가 필요하고 textField에는 키보드가 표시 될 때 창에 애니메이션을 적용하기 위해 textFieldDidBeginEditing을 사용하는 하위 클래스가 필요합니다. 애니메이션은 키보드로 창을 이동합니다. 키보드가 textField를 덮지 않도록이 메서드를 사용합니다.
Gaucho

10

이것은 UITextView에서 전체 선택 / 복사 / 붙여 넣기 메뉴를 비활성화하는 가장 쉬운 방법입니다.

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

UITextField에서도 작동합니다. 공유해 주셔서 감사합니다.
Gaurav 스리 바스타

1
나는 여전히 위의 코드를 사용하고 있는데 메뉴를 비활성화하는 방법을 알고 있습니다.
Bittoo

4

iOS 7부터 UITextView에 속성이 있습니다.

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

이렇게하면보기에서 텍스트 선택을 허용하지 않습니다. 나를 위해 잘 작동합니다.


4

키보드를 a로 교체하려는 UIPicker경우 inputView(물론 도구 모음이으로 inputAccesotyView)이 해결 방법이 도움이 될 수 있습니다.

  • 도구 textFieldShouldBeginEditing:
  • 안에 넣어 textField.userInteractionEnabled = NO;
  • 그런 다음을 닫으려고 할 때 UIPickerViewYES로 설정하십시오.

이렇게하면을 탭 UITextField하고에서 선택할 수있는 옵션을 표시 할 수 있습니다 UIPickerView. 현재로서는 UITextField터치 이벤트에 반응하지 않을 것입니다 (여기에는 잘라 내기, 복사 및 붙여 넣기를위한 길게 터치 포함). 그러나 닫을 때 다시 YES로 설정해야 UIPickerView하지만 UIPickerView다시 액세스 할 수 없습니다 .

실패하는 유일한 순간은 사용자가을 길게 눌러 시작 UITextView하면 처음으로 잘라 내기 복사 및 붙여 넣기가 표시됩니다. 이것이 항상 입력의 유효성을 검사해야하는 이유입니다. 이것이 제가 생각할 수있는 가장 쉬운 방법입니다. 다른 옵션은 UILabel읽기 전용 텍스트 에를 사용하는 것이었지만 UITextView.


4

하위 클래스 UITextView-스위프트 4.0

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

얼마나 이상해? 여전히 "붙여 넣기"옵션이 표시되지만 눌려도 실행되지 않습니다 ...
iOS Flow

4

팝업을 비활성화하려면 UITextFieldUITextFieldDelegate방법을 사용하여 isUserInteractionEnabled.

func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
    textField.isUserInteractionEnabled = false
    return true
}
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
    textField.isUserInteractionEnabled = true
    return true
}

3

이것은 스토리 보드 (Xcode 6)에서 쉽게 수행 할 수 있습니다. Attributes Inspector에서 Editable and Selectable을 선택 취소하십시오. 여전히 텍스트보기를 스크롤 할 수 있습니다.여기에 이미지 설명 입력


3

이것은 나를 위해 일했습니다. textView에서 resignFirstResponder를 호출하고 있는지 확인하십시오.

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

2

여기 에 텍스트 선택 + 돋보기를 비활성화하고 클릭 가능한 링크를 활성화하는 데 도움이 되는 작업 답변을 제공했습니다 .

오랜 시간 동안 시도한 끝에 UITextView 하위 클래스에서 addGestureRecognizer를 재정 의하여 터치 종료를 지연시키는 UILongPressGestureRecognizer 만 허용하여 텍스트 선택, 확대 및 데이터 감지 (링크 클릭 가능 등)를 중지 할 수있었습니다.

UIUnselectableTextView.m

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

2

들어 스위프트 3 그것은 할 변경된 :

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

2

다음 상자를 선택 취소하여 스토리 보드에서이 문제를 해결할 수 있습니다.

여기에 이미지 설명 입력

또는 다음과 같이 프로그래밍 방식으로 설정할 수 있습니다.

textView.selectable = false
textView.editable = false

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

    }
}

그리고 그것은 나를 위해 일했습니다. 감사합니다.


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.

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)")

    }

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

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

1
이것은 그것을 해결하는 좋은 방법이 아닙니다. 첫째, 카테고리에있는 모든 것에 영향을 미칩니다. 둘째, 비교적 쉬운 작업을 위해 관련 객체를 사용하면 이익을 제공하는 것보다 나중에 디버깅에 더 많은 문제가 발생할 수 있습니다. 제 생각에는 가능한 한 피하는 것이 좋습니다. 프로젝트의 새로운 프로그래머가 코드를 찾고 디버그하고 이해하기가 더 쉬워집니다.
Vive

0

서브 클래 싱 UITextView및 재정의 - (void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer는 원하지 않는 작업을 비활성화 할 수있는 또 다른 가능성입니다.

gestureRecognizer-object 의 클래스를 사용하여 조치를 추가해야하는지 여부를 결정하십시오.


0

(SWIFT) 메뉴 옵션이나 돋보기가없는 기본 텍스트 필드 만 원하면 gestureRecognizerShouldBegin에 false를 반환하는 UITextField의 하위 클래스를 만듭니다.

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()

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

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

0

UITextView에는 필요한 작업을 수행하는 두 가지 속성이 있습니다. isSelectableisEditable 입니다.

isEditable을 false로 설정하면 사용자가 텍스트를 편집하는 것을 방지하고 isSelectable 을 false로 설정 하면 사용자가 textView 내에서 텍스트를 선택하는 것을 방지 할 수 있으므로 작업 메뉴가 표시되지 않습니다.


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
    }

-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로 클래스 새 클래스 추가

여기에 이미지 설명 입력

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.