你如何真正从UIMenuController中删除Copy

时间:2011-07-07 17:14:04

标签: ios cocoa-touch uimenucontroller

当您添加多个自定义菜单项时,显然曾经有easy way来阻止“更多...”标签出现在UIMenuController中。您只需删除所有系统菜单项。甚至有workaround here仍有复制工作。您只需使用不同的选择器实现自定义复制命令,然后覆盖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>.

6 个答案:

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

答案 1 :(得分:7)

for ios&gt; = 5.1 canPerformAction:(SEL)action withSender :( id)发送者不再工作。

如果您只是禁用粘贴操作,可以使用以下方法:

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

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

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

强制用户输入电子邮件和

等文本字段是一种很好的做法

答案 2 :(得分:3)

lemnar的回答是正确的。实现UIWebView的子类工作得很好。对于UITextView,这个example是可以的。对于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];
}

答案 3 :(得分: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:这个优秀的网页上有一个小错字。这正是你如何做到的。 Apple将 100%拒绝此。制作类别

enter image description here

(您必须输入“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%拒绝。

答案 4 :(得分:1)

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

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

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

答案 5 :(得分:0)

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

相关问题