优雅的使用 WebViewJavaScriptBridge 注册方法

最近研究 WebViewJavaScriptBridge ,网上原理讲的大致都一样,结合自己看看源码,流程都弄清楚了,总结一下。
1 WebViewJavaScriptBridge 配合 WKWebView 使用的还是 拦截URL的方法 实现 JS 与 WebView的交互。简单的使用,先在页面加载完后,注入JS到页面,JS 方法调用时会将参数等转换使webview能拦截识别。内部使用 类似字典的机制,存储注册的方法名,和相应的处理。
2 官方文档给的注册方法的例子

 [self.jsBridge registerHandler:jsName
            handler:^(id data, WVJBResponseCallback responseCallback) {
                                  //
                               }];

这种情况简单的还好,但是涉及到方法比较多的时候,会比较头疼。
我的解决方案是创建一个类,专门处理 JS 的调用。类中方法名字和 JS 调用的相同,通过 runtime 获取方法列表,然后向 self.jsBridge 注册方法。通过分发的方式调用方法。最后的样子是这样

//注册 JS
    for (NSString *jsName in [self.helper.ymHelperMethodDic allKeys]) {
    
        __weak typeof(self) weakSelf = self;
        [self.jsBridge registerHandler:jsName
                               handler:^(id data, WVJBResponseCallback responseCallback) {
                                   __strong typeof(weakSelf) strongSelf = weakSelf;
                                   [strongSelf.helper ymHelperHandleName:jsName
                                                              data:data
                                                          callBack:responseCallback];
                               }];

    }

具体的解决思路,先获取方法列表,和转换后的 JSName ,记得过滤掉不相干的方法。

/**
 *  通过runtime 获取方法列表
 *
 *  @return 方法名 和 js名 组成 的 字典
 */
- (NSDictionary *)ymHelperMethodListDic
{
    unsigned int count;
    Method *methods = class_copyMethodList([WebViewJSHandler class], &count);
    NSMutableDictionary *methodDictionary = [NSMutableDictionary dictionaryWithCapacity:count];
    
    for (int i = 0; i < count; i++)
    {
        Method method = methods[i];
        SEL selector = method_getName(method);
        NSString *name = NSStringFromSelector(selector);
        
        /**
         *  过滤掉私有的方法
         */
        if (![name containsString:@"mHelper"] &&
            ![name containsString:@"."] &&
            ![name containsString:@"dealloc"]) {
            
            NSString *jsName = [[name componentsSeparatedByString:@":"] firstObject];
            NSLog(@"方法 名字 ==== %@",name);
            NSLog(@"js 名字 ==== %@",jsName);
            [methodDictionary setObject:name forKey:jsName];
        }
        
    }
    return methodDictionary;
}

拿到字典成功一半。通过 JSName 转换 SEL ,然后再做转发。

/**
 *  通过 methodName 做转发
 *
 *  @param methodName       方法名称
 *  @param data             数据
 *  @param responseCallback 回调
 */
- (void)ymHelperHandleName:(NSString *)methodName
              data:(id)data
          callBack:(YMResponseCallback)responseCallback{
    
    NSString *selString = [self ymHelperFindSELByJSName:methodName];
    //转换 string to SEL
    SEL sel = NSSelectorFromString(selString);
    
    if ([self.ymHelperWebViewJSHandler respondsToSelector:sel]) {
        
//忽略警告
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        [self.ymHelperWebViewJSHandler performSelector:sel withObject:data withObject:responseCallback];
#pragma clang diagnostic pop
    }   
}

然后通过 performSelector 的方式做转发。

在 web view里面 就通过这样就搞定了

//注册 JS
    for (NSString *jsName in [self.helper.ymHelperMethodDic allKeys]) {
    
        __weak typeof(self) weakSelf = self;
        [self.jsBridge registerHandler:jsName
                               handler:^(id data, WVJBResponseCallback responseCallback) {
                                   __strong typeof(weakSelf) strongSelf = weakSelf;
                                   [strongSelf.helper ymHelperHandleName:jsName
                                                              data:data
                                                          callBack:responseCallback];
                               }];

    }

不用在 一个 controller 里面写一堆注册方法的实现。

你可能感兴趣的:(优雅的使用 WebViewJavaScriptBridge 注册方法)