ios 你如何真正从 UIMenuController 中删除 Copy

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6614465/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 20:39:34  来源:igfitidea点击:

How do you REALLY remove Copy from UIMenuController

ioscocoa-touchuimenucontroller

提问by lfalin

There apparently used to be an easy wayto prevent the "More..." label from appearing in UIMenuController when you added more than one custom menu item. You just had to remove all of the system menu items. There was even a workaround herefor still having copy work. You just had to implement a custom copy command using a different selector and then override canPerformAction:withSender: to not show the system copy:

当您添加多个自定义菜单项时,显然曾经有一种简单的方法可以防止“更多...”标签出现在 UIMenuController 中。您只需删除所有系统菜单项。这里甚至还有一个解决方法,用于仍然进行复制工作。您只需使用不同的选择器实现自定义复制命令,然后覆盖 canPerformAction:withSender: 以不显示系统副本:

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender 
{
    if (action == @selector(copy:))
       return NO;
    else
       // logic to show or hide other things
}

Unfortunately this method no longer works (at least in a UIWebView subclass). canPerformAction:withSender: is called for every system menu item except copy: so the result is that the system copy menu item is always displayed. This means that if you have more than one custom menu item, they are always hidden behind "More..."

不幸的是,此方法不再有效(至少在 UIWebView 子类中)。canPerformAction:withSender: 为除 copy: 之外的每个系统菜单项调用:因此结果是始终显示系统复制菜单项。这意味着如果您有多个自定义菜单项,它们总是隐藏在“更多...”后面。

So, is there a way to really remove the system's copy item or some alternate way to prevent menu items from hiding behind "More..."?

那么,有没有办法真正删除系统的复制项或某种替代方法来防止菜单项隐藏在“更多...”后面?

Update

更新

This is the output I get when I override canPerformAction:withSender: notice that the method is never called for the "copy:" action:

这是我在覆盖 canPerformAction:withSender 时得到的输出:请注意,该方法永远不会为“复制:”操作调用:

cannot perform action cut: with sender <UIMenuController: 0x7227d30>.
cannot perform action select: with sender <UIMenuController: 0x7227d30>.
cannot perform action selectAll: with sender <UIMenuController: 0x7227d30>.
cannot perform action paste: with sender <UIMenuController: 0x7227d30>.
cannot perform action delete: with sender <UIMenuController: 0x7227d30>.
cannot perform action promptForReplace: with sender <UIMenuController: 0x7227d30>.
cannot perform action _showMoreItems: with sender <UIMenuController: 0x7227d30>.
cannot perform action _setRtoLTextDirection: with sender <UIMenuController: 0x7227d30>.
cannot perform action _setLtoRTextDirection: with sender <UIMenuController: 0x7227d30>.
can perform action customCopy: with sender <UIMenuController: 0x7227d30>.
can perform action custom1: with sender <UIMenuController: 0x7227d30>.
cannot perform action custom2: with sender <UIMenuController: 0x7227d30>.
can perform action custom3: with sender <UIMenuController: 0x7227d30>.
can perform action custom4: with sender <UIMenuController: 0x7227d30>.
cannot perform action cut: with sender <UIMenuController: 0x7227d30>.
cannot perform action select: with sender <UIMenuController: 0x7227d30>.
cannot perform action selectAll: with sender <UIMenuController: 0x7227d30>.
cannot perform action paste: with sender <UIMenuController: 0x7227d30>.
cannot perform action delete: with sender <UIMenuController: 0x7227d30>.
cannot perform action promptForReplace: with sender <UIMenuController: 0x7227d30>.
cannot perform action _showMoreItems: with sender <UIMenuController: 0x7227d30>.
cannot perform action _setRtoLTextDirection: with sender <UIMenuController: 0x7227d30>.
cannot perform action _setLtoRTextDirection: with sender <UIMenuController: 0x7227d30>.

采纳答案by lemnar

The technique you linked to still seems to work. I implemented a UIWebViewsubclass with these methods, and only the A and B items appeared.

您链接的技术似乎仍然有效。我UIWebView用这些方法实现了一个子类,只出现了 A 和 B 项。

+ (void)initialize
{
    UIMenuItem *itemA = [[UIMenuItem alloc] initWithTitle:@"A" action:@selector(a:)];
    UIMenuItem *itemB = [[UIMenuItem alloc] initWithTitle:@"B" action:@selector(b:)];
    [[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObjects:itemA, itemB, nil]];
    [itemA release];
    [itemB release];
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    BOOL can = [super canPerformAction:action withSender:sender];
    if (action == @selector(a:) || action == @selector(b:))
    {
        can = YES;
    }
    if (action == @selector(copy:))
    {
        can = NO;
    }
    NSLog(@"%@ perform action %@ with sender %@.", can ? @"can" : @"cannot", NSStringFromSelector(action), sender);
    return can;
}

回答by Canberk Ersoy

for ios >= 5.1 canPerformAction:(SEL)action withSender:(id)sender is not working anymore.

对于 ios >= 5.1 canPerformAction:(SEL)action withSender:(id)sender 不再工作。

If you are ok with just disable paste action here is a method:

如果您只需禁用粘贴操作就可以了,这是一种方法:

add UITextFieldDelegate to you view controller and implement method like this

将 UITextFieldDelegate 添加到您的视图控制器并实现这样的方法

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
if(textField == txtEmailRe)
    return ((string.length) > 1 ? NO : YES);
}

it means that if user enter more than one character for each action (it means that probably user is pasting something.) do not accept it in textfield.

这意味着如果用户为每个操作输入多个字符(这意味着用户可能正在粘贴某些内容。)不要在文本字段中接受它。

it is a good practice for force user enter textfields like e-mail and

强制用户输入文本字段(如电子邮件和

回答by Adriano Lucas

lemnar's answer is correct. Implementing a subclass of UIWebView works just fine. This exampleis OK for a UITextView. For a UIWebView, create a custom subclass as follows:

lemnar 的回答是正确的。实现 UIWebView 的子类工作得很好。这个例子适用于 UITextView。对于 UIWebView,创建自定义子类如下:

//
//  MyUIWebView.h
//

#import <UIKit/UIKit.h>

@interface MyUIWebView : UIWebView

@end

And:

和:

//
//  MyUIWebView.m
//

#import "MyUIWebView.h"

@implementation MyUIWebView

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender 
{
    if (action == @selector(copy:))
        return NO;
    else
        // logic to show or hide other things
}

@end

Then, instead of instantiating UIWebView, use MyUIWebView.

然后,不要实例化 UIWebView,而是使用 MyUIWebView。

UPDATE:

更新

If wanting to disable "copy" but leave "define" (and "translate",) which can be useful, this is how to do it; replace canPerformAction:withSenderabove with this:

如果想禁用“复制”但保留可能有用的“定义”(和“翻译”),这是如何做到的;canPerformAction:withSender用这个替换上面的:

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender 
{
    if (action == @selector(defineSelection:))
    {
        return YES;
    }
    else if (action == @selector(translateSelection:))
    {
        return YES; 
    }
    else if (action == @selector(copy:))
    {
        return NO;
    }

    return [super canPerformAction:action withSender:sender];
}

回答by auco

Here is a solution for iOS5.x that works for me. It's by Josh Garnham, suggesting creating a UIWebBrowserView Category to catch the copy:, paste:, define: selectors.

这是适用于我的 iOS5.x 解决方案。它是由 Josh Garnham 编写的,建议创建一个 UIWebBrowserView 类别来捕获复制:、粘贴:、定义:选择器。

http://ios-blog.co.uk/iphone-development-tutorials/rich-text-editing-highlighting-and-uimenucontroller-part-3/

http://ios-blog.co.uk/iphone-development-tutorials/rich-text-editing-highlighting-and-uimenucontroller-part-3/

@implementation UIWebBrowserView (UIWebBrowserView_Additions)
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    return NO;
}
@end


Note just FTR: There's a slight typo on that excellent web page. Here's precisely how you do it. Apple will 100% reject this.Make a category

请注意 FTR:那个优秀的网页上有一个轻微的错字。这正是你如何做到的。苹果将100% 拒绝这一点。创建一个类别

enter image description here

在此处输入图片说明

(You have to type in "UIWebBrowserView" since Xcode won't bring up private classes.) Full text of the .h and .m files:

(您必须输入“UIWebBrowserView”,因为 Xcode 不会显示私有类。).h 和 .m 文件的全文:

// .h file...
#import "UIWebBrowserView+Tricky.h"
@interface UIWebBrowserView : UIView
@end
@interface UIWebBrowserView(Tricky)
@end

// .m file...
#import "UIWebBrowserView+Tricky.h"
@implementation UIWebBrowserView (Tricky)
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
NSLog(@"don't let Apple see this");
return NO;
}
@end

For the record, a "single click" will still bring up the annoying spellchecker suggestions! But otherwise it does remove the double-click-context-menu totally, it is 100% rejected by Apple.

为了记录,“单击”仍然会带来烦人的拼写检查建议!但除此之外,它确实完全删除了双击上下文菜单,Apple 100% 拒绝了它。

回答by sandycs

I'm sorry for my English. But there is an idea.

我为我的英语感到抱歉。但是有一个想法。

I think the method canPerformAction were called for many times but you just deal with it once. In this case ,I think there may be another UI Control has called it. For example, the UITextView control in your UIWebView.

我认为 canPerformAction 方法被调用了很多次,但你只处理一次。在这种情况下,我认为可能有另一个 UI 控件调用了它。例如,您的 UIWebView 中的 UITextView 控件。

I guess you may generate the UI by storyboard. Not every control in storyboard has its own class. You can define a class for the response control and rewrite its canPerformAction method.

我猜您可能会通过故事板生成 UI。并非故事板中的每个控件都有自己的类。您可以为响应控件定义一个类并重写其 canPerformAction 方法。

回答by LaC

You could draw your own menu instead of using UIMenuController. That way, you can have as many items as you want displayed at the same time without using Other.

您可以绘制自己的菜单而不是使用 UIMenuController。这样,您可以在不使用其他的情况下同时显示任意数量的项目。