Disable entire UIMenuController edit menu in WKWebView

davew picture davew · Oct 20, 2015 · Viewed 7.2k times · Source

Requirement

I have a WKWebView and would like to remove the system menu items (Copy, Define, Share...) from the Edit Menu and present my own.

I am targeting iOS 8 and 9. I am currently testing with the Xcode 7.0.1 simulator (iOS 9) and my iPhone 6 running iOS 9.0.2.

Standard Method Does Not Work

I know the standard way of achieving this is by subclassing WKWebView and implementing -canPerformAction:withSender:. However, I have found that with WKWebView -canPerformAction:withSender: is not being called for the copy: or define: actions. This appears to be a known bug (WKWebView and UIMenuController).

Example app: https://github.com/dwieringa/WKWebViewCustomEditMenuBug

@implementation MyWKWebView

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    NSLog(@"ACTION: %@", NSStringFromSelector(action));

    if (action == @selector(delete:))
    {
        // adding Delete as test (works)
        return YES;
    }

    // trying to remove everything else (does NOT work for Copy, Define, Share...)
    return NO;
}

- (void)delete:(id)sender
{
    NSLog(@"Delete menu item selected");
}

@end

Output: (note no copy: or define: action)

2015-10-20 12:28:32.864 WKWebViewCustomEditMenuBug[45804:21121480] ACTION: cut:
2015-10-20 12:28:32.865 WKWebViewCustomEditMenuBug[45804:21121480] ACTION: select:
2015-10-20 12:28:32.865 WKWebViewCustomEditMenuBug[45804:21121480] ACTION: selectAll:
2015-10-20 12:28:32.865 WKWebViewCustomEditMenuBug[45804:21121480] ACTION: paste:
2015-10-20 12:28:32.866 WKWebViewCustomEditMenuBug[45804:21121480] ACTION: delete:
2015-10-20 12:28:32.866 WKWebViewCustomEditMenuBug[45804:21121480] ACTION: _promptForReplace:
2015-10-20 12:28:32.866 WKWebViewCustomEditMenuBug[45804:21121480] ACTION: _transliterateChinese:
2015-10-20 12:28:32.867 WKWebViewCustomEditMenuBug[45804:21121480] ACTION: _showTextStyleOptions:
2015-10-20 12:28:32.907 WKWebViewCustomEditMenuBug[45804:21121480] ACTION: _addShortcut:
2015-10-20 12:28:32.908 WKWebViewCustomEditMenuBug[45804:21121480] ACTION: _accessibilitySpeak:
2015-10-20 12:28:32.908 WKWebViewCustomEditMenuBug[45804:21121480] ACTION: _accessibilitySpeakLanguageSelection:
2015-10-20 12:28:32.908 WKWebViewCustomEditMenuBug[45804:21121480] ACTION: _accessibilityPauseSpeaking:
2015-10-20 12:28:32.909 WKWebViewCustomEditMenuBug[45804:21121480] ACTION: makeTextWritingDirectionRightToLeft:
2015-10-20 12:28:32.909 WKWebViewCustomEditMenuBug[45804:21121480] ACTION: makeTextWritingDirectionLeftToRight:

Planned Workaround

My desire now is to completely hide the edit menu and replace it with a custom menu using QBPopupMenu.

My problem is that I have not been able to find a way to hide or disable the standard Edit menu. I have found some suggestions to hide it with [UIMenuController sharedMenuController].menuVisible = NO; on UIMenuControllerWillShowMenuNotification, but I have not been able to get this to work. It has no affect with WillShowMenu. I can hide it in DidShowMenu but by that point it is too late and I get a menu flash.

I have also tried to locate it outside the visible area using [[UIMenuController sharedMenuController] setTargetRect:CGRectMake(0, 0, 1, 1) inView:self.extraView];, but again doing so with WillShowMenu has no affect and with DidShowMenu it is too late.

Experiments available here: https://github.com/dwieringa/WKWebViewEditMenuHidingTest

What am I missing? Is there another way to disable or hide the standard editting menu for WKWebView?

Answer

Paulo Cesar picture Paulo Cesar · Dec 11, 2015

Based on your workaround, I found out that:

-(void)menuWillShow:(NSNotification *)notification
{
    NSLog(@"MENU WILL SHOW");

    dispatch_async(dispatch_get_main_queue(), ^{
        [[UIMenuController sharedMenuController] setMenuVisible:NO animated:NO];
    });

}

Will prevent the menu from flashing 90% of the times.. Still not good enough, but it's another workaround before we find a decent solution.