2
votes

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?

4

4 Answers

7
votes

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

5
votes

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.

2
votes

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

public extension UITextView {
    override 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:)!

1
votes

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