美文网首页WebView 各种相关
iOS WKWebView长按自定义菜单功能

iOS WKWebView长按自定义菜单功能

作者: 核桃酥8016 | 来源:发表于2021-11-04 17:00 被阅读0次

    最近做需求时碰到了要webview自定义MenuItem的功能,系统自带的菜单栏显示很多item用不着

    系统自带的item

    以前做过类似的需求,但是搞完后发现在iOS15系统上显示不对,还是会有系统的copy等,最终通过runtime交换wkwebview的系统方法解决。

    解决方法
    1、自定义一个wkwebview的钩子hook类,用自定义的方法替换系统的方法
    @implementation WELWKWebViewMenuHook

    + (void)load{

        staticdispatch_once_tonceToken;

        dispatch_once(&onceToken, ^{

            Method  m =class_getInstanceMethod(NSClassFromString(@"WKContentView"), NSSelectorFromString(@"canPerformAction:withSender:"));

            class_addMethod(NSClassFromString(@"WKContentView"), NSSelectorFromString(@"wel_canPerformAction:withSender:"), (IMP)wel_canPerformAction, method_getTypeEncoding(m));

            Method m1 = class_getInstanceMethod(NSClassFromString(@"WKContentView"),NSSelectorFromString(@"canPerformAction:withSender:"));

            Method m2 = class_getInstanceMethod(NSClassFromString(@"WKContentView"), NSSelectorFromString(@"wel_canPerformAction:withSender:"));

            method_exchangeImplementations(m1,m2);

            Method  M =class_getInstanceMethod(NSClassFromString(@"WKWebView"), NSSelectorFromString(@"canPerformAction:withSender:"));

            class_addMethod(NSClassFromString(@"WKWebView"), NSSelectorFromString(@"wel_canPerformAction:withSender:"), (IMP)wel_canPerformAction, method_getTypeEncoding(M));

            Method M1 = class_getInstanceMethod(NSClassFromString(@"WKWebView"),NSSelectorFromString(@"canPerformAction:withSender:"));

            Method M2 = class_getInstanceMethod(NSClassFromString(@"WKWebView"), NSSelectorFromString(@"wel_canPerformAction:withSender:"));

            method_exchangeImplementations(M1,M2);

        });

    }

    上面方法实现了把系统的WKWebView和WKContentView中响应item的方法替换为自定义方法wel_canPerformAction,然后在wel_canPerformAction方法中实现
    BOOLwel_canPerformAction(idself,  SEL_cmd,SELarg1,idarg2) {

        NSString*actionString =NSStringFromSelector(arg1);

        BOOL isShowQyMenuItem = [[[NSUserDefaults standardUserDefaults] objectForKey:@"KIsShowQYMenuItem"] boolValue];//bool值来控制是否需要显示自定义的menuItem

        if([actionStringisEqualToString:@"qy_addNotes:"] || [actionStringisEqualToString:@"qy_collection:"] || [actionStringisEqualToString:@"qy_share:"] || [actionStringisEqualToString:@"qy_copy:"]) {

            returnisShowQyMenuItem;

        }else{

            return!isShowQyMenuItem;

        }

    }
    此方法返回yes就显示对应的item,返回no就不显示,所以在此方法中根据自定义的方法名字来显示想要的item,hook类中就实现这两个方法就ok,接下来是在自定义的wkwebview中实现方法。
    2、自定义继承WKWebView的类,实现每个item对应的方法,举个例子,

    - (void)qy_addNotes:(UIMenuController *)menu

    {

        [self evaluateJavaScript:@"window.getSelection().toString()" completionHandler:^(id _Nullable content, NSError * _Nullable error) {

            NSString*selectContent = (NSString*)content;

            NSLog(@"选中-----%@", selectContent);

            if(self.noteBlock) {

                self.noteBlock(selectContent);

            }

        }];

    }

    其中window.getSelection().toString()是获取当前选中的内容,然后通过block或者代理就可以把item方法传递到继承这个wkwebview的子类中来做相应的操作了。

    最终解决了问题

    最后附上demo:https://github.com/726491400/CustomMenuItem
    感谢大佬的文章:https://www.jianshu.com/p/dd7452d3d123

    相关文章

      网友评论

        本文标题:iOS WKWebView长按自定义菜单功能

        本文链接:https://www.haomeiwen.com/subject/plurzltx.html