How to disable Copy & Define UIMenuItems of UIMenu

2019-04-14 18:29发布

问题:

I am implementing custom UIMenuController and trying to figure out. How can I legally disable "Copy" and "Define" UIMenuItems of UIMenuController in UITextfield? Textfield is not editable. I tried to disable "Copy" using:

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

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


- (IBAction)tapTextViewGesture:(id)sender {

  UIMenuItem *myItem1 = [[UIMenuItem alloc] initWithTitle:@"myItem1" action:@selector(myItem1Pressed:)];
  UIMenuItem *myItem2 = [[UIMenuItem alloc] initWithTitle:@"myItem2" action:@selector(myItem2Pressed:)];
  UIMenuItem *myItem3 = [[UIMenuItem alloc] initWithTitle:@"myItem3" action:@selector(myItem3Pressed:)];

    // Access the application's shared menu
    UIMenuController *menu = [UIMenuController sharedMenuController];

    [menu setMenuItems:[NSArray arrayWithObjects:myItem1,myItem2,myItem3, nil]];

    CGRect menuRect = CGRectMake(20, 50, 200, 0);


    // Show the menu from the cursor's position
    [menu setTargetRect:menuRect inView:self.view];


    [menu setMenuVisible:YES animated:YES];
}

But the menu is still showing "Copy" and "Define" UIMenuItems. How can I disable them, leaving only my items?

回答1:

Finally solved it by subclassing UITextView (created custom class for it) and just added

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{

    if (action == @selector(copy:))
    {
        return NO;
    }

    return NO;
}

inside of .m file of my custom TextView subclass.

After that "Copy" doesn't appear any more, with or without [menu update];



回答2:

Implement this instance method in viewController.m:

**- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    if ([_targetTextField isFirstResponder]) {
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [[UIMenuController sharedMenuController] setMenuVisible:NO animated:NO];
        }];
    }
    return [super canPerformAction:action withSender:sender];
}**

This method checks if targeted text field is the first responder or not. If it is, NSOperationQueue creates a separate thread for sharedMenuController operation, set its visibility and animation as no so that it couldn't work for copy, paste,etc. The return statement calls UIResponder's canPerformAction method to inform for the same to implement it.



回答3:

You can do this by making a class by subclassing UITextField class and overriding its canPerformAction:: method.

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    // Returning 'NO' here disables all actions on textfield
    return NO;
}


回答4:

Swift 4.2. && Xcode 10 that works for me:

    override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        // Requested action to prevent: 
        guard action != #selector(copy(_:)) else { return false }      // disabling copy

        // Further actions to prevent: 
        // guard action != #selector(cut(_:)) else { return false }    // disabling cut
        // guard action.description != "_share:" else { return false } // disabling share 
        return super.canPerformAction(action, withSender: sender)
}

In order to make this work you must create a subclass of UITextField/UITextView and make sure to call super on super.canPerformAction(_:withSender:)!



回答5:

Add this after you set your menu items

[menu update];

I hope this solves your query. :)