21

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

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

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

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

更新

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

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

6 回答 6

13

您链接到的技术似乎仍然有效。我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;
}
于 2011-08-07T11:09:28.507 回答
7

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

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

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

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

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

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

于 2012-06-13T07:52:27.097 回答
3

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

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

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

在此处输入图像描述

(您必须输入“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

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

于 2012-01-28T21:54:12.363 回答
3

lemnar 的回答是正确的。实现 UIWebView 的子类就可以了。此示例适用于 UITextView。对于 UIWebView,创建一个自定义子类,如下所示:

//
//  MyUIWebView.h
//

#import <UIKit/UIKit.h>

@interface MyUIWebView : UIWebView

@end

和:

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

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

更新

如果想禁用“复制”但保留“定义”(和“翻译”),这可能很有用,这就是如何做到的;将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];
}
于 2011-10-30T11:35:58.343 回答
1

对不起我的英语。但是有一个想法。

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

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

于 2012-05-22T00:37:50.410 回答
0

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

于 2011-08-04T19:27:29.893 回答