需求:
WKWebView里的文字如果长按的话,会出现UIMenuController菜单快捷键包括:拷贝、粘贴、全选、翻译、查询、学习、共享等功能。当然,苹果给我们提供如此便捷的菜单是好事,我们能不能屏蔽一下不需要的菜单呢?
方案一:
可以通过css、js等屏蔽长按操作。贴代码:
// 禁止选择CSS
NSString *css = @"body{-webkit-user-select:none;-webkit-user-drag:none;}";
// CSS选中样式取消
NSMutableString *javascript = [NSMutableString string];
[javascript appendString:@"var style = document.createElement('style');"];
[javascript appendString:@"style.type = 'text/css';"];
[javascript appendFormat:@"var cssContent = document.createTextNode('%@');", css];
[javascript appendString:@"style.appendChild(cssContent);"];
[javascript appendString:@"document.body.appendChild(style);"];
// javascript注入
WKUserScript *noneSelectScript = [[WKUserScript alloc] initWithSource:javascript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
WKUserContentController *userContentController = [[WKUserContentController alloc] init];
[userContentController addUserScript:noneSelectScript];
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
configuration.userContentController = userContentController;
好处是彻底封杀长按菜单,坏处是无法保留我们想要的拷贝等基本功能。
方案二:
重写WKWebView的canPerformAction:withSender:方法,将需要的返回YES,不需要的返回NO。
重点:是重写WKWebView的方法哦!
#import <WebKit/WebKit.h>
@interface HXWebView : WKWebView
@end
@implementation HXWebView
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
//NSLog(@"action:%@",NSStringFromSelector(action));
//我们在这里不要去处理私有API的方法,会被苹果检测出来的哦!
if(action ==@selector(copy:) ||
action ==@selector(selectAll:)||
action ==@selector(cut:)||
action ==@selector(select:)||
action ==@selector(paste:)) {
//记得调用super的方法哦!
return [super canPerformAction:action withSender:sender];
}
return NO;
}
@end
方案三:
如果是iOS 11以上的项目,还可以通过hook方式替换全部的canPerformAction:withSender:方法。好处是无侵入替换整个项目的WKWebView。
#import <WebKit/WebKit.h>
@interface WKWebView (HXWebView)
@end
@implementation WKWebView (HXWebView)
+ (void)load
{
if (@available(iOS 11, *)) {
SEL originalSelector = @selector(canPerformAction:withSender:);
SEL swizzledSelector = @selector(ex_canPerformAction:withSender:);
Class class = WKWebView.class;
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
- (BOOL)ex_canPerformAction:(SEL)action withSender:(id)sender
{
//我们在这里不要去处理私有API的方法,会被苹果检测出来的哦!
if(action == @selector(copy:)||
action == @selector(selectAll:)||
action == @selector(cut:)||
action == @selector(select:)||
action == @selector(paste:)) {
return [self ex_canPerformAction:action withSender:sender];
}
return NO;
}
@end
更新:iOS 16适配
大家可能主要到了,iOS 16系统上会自动增加新的“在网页查找”等菜单。只靠上面的方法无法彻底屏蔽所有菜单。需要对iOS 16进行适配一下即可:
- (void)buildMenuWithBuilder:(id<UIMenuBuilder>)builder
{
if (@available(iOS 16, *)) {
[builder removeMenuForIdentifier:UIMenuLookup];
}
}
我们在这里不要去处理私有API的方法,会被苹果检测出来的哦!
_define:
_promptForReplace:
_share:
_transliterateChinese:
_insertDrawing:
_showTextStyleOptions:
_lookup:
_addShortcut:
_accessibilitySpeak:
_accessibilitySpeakLanguageSelection:
_accessibilityPauseSpeaking:
最后是记得调用super的方法哦!要知道这里面的处理逻辑还是很复杂的呢!
附上WKWebView的源码链接:https://github.com/WebKit/WebKit