iOS 开发之 OC 与 JS 的通信桥梁:WebViewJavascriptBridge

前言

当下,移动端 APP 嵌套 HTML5 网页已成常态,我们除了简单地用 WebView 加载显示之外,很多情况下,我们还需要和 WebView 进行交互,比如点击 WebView 上面的按钮调用 OC 端的函数实现具体的操作……

iOS 开发中,H5 和原生交互有多种方式, JSBridge 就是最常用的一种,各 JSBridge 类库的实现原理大同小异…今天呢,介绍一下盛名已久的 WebViewJavascriptBridge ,它主要帮助我们优雅地实现 OC 与 JS 的交互,非常方便简洁。

目录结构


WebViewJavascriptBridge
  1. WebViewJavascriptBridge_JS

JS 端用来收发消息的类,纯 JS 代码。其做为 html 的 bridge,负责(主动)对原生界面发送消息,整理并(被动的向原生界面)传输数据,并向 html 发送回调信息;

  1. WebViewJavascriptBridge

桥接的入口,针对不同类型的 webView(UIWebView,WKWebView,WebView)进行分发;
针对 UIWebView 和 WebView 做的一层封装,主要用来执行 JS 代码,以及实现 UIWebView 和 WebView的代理方法,并通过拦截 URL 来通知 WebViewJavascriptBridgeBase 做相应操作

  1. WKWebViewJavascriptBridge

针对 WKWebView 做的一层封装,主要用来执行 JS 代码,以及实现 WKWebView 的代理方法,并通过拦截 URL 来通知 WebViewJavascriptBridgeBase 做相应操作

  1. WebViewJavascriptBridgeBase

用来进行 bridge 初始化和消息处理的核心类;
这个类是在支持 WKWebView 后从 WebViewJavascriptBridge 中独立出来的逻辑,专门用来处理 bridge 相关的逻辑,不再与具体的 Web View 相关联了

理一下它们的关系

WebViewJavascriptBridge_JS 可以看成是 html 文件中 JS 代码的 bridge,主要服务于 html 中的 JS 方法功能的;另外的三个 WebViewJavascriptBridge, WKWebViewJavascriptBridge, WebViewJavascriptBridgeBase 是 webView 的 bridge,主要服务于原生的。这两个 bridge 之间主要通过 webView 的代理方法webView:decidePolicyForNavigationAction:decisionHandler: 和 stringByEvaluatingJavaScriptFromString: 方法进行消息的传递和数据的传输。

众所周知,WKWebView 和 UIWebView 的性能差异很大。WKWebView 比 UIWebView 加载网页的速度更快,效率更高,内存消耗小,所以现在在开发中我都是选择使用 WKWebView。

并且,在当前时间节点,大多数 iOS App 都是基于 iOS 8.0+ 的,这是一个 WKWebView 的时代。

使用步骤

1、导入 WebViewJavaScriptBridge 框架:

pod ‘WebViewJavascriptBridge’

2、创建 WKWebView 和 WKWebViewJavascriptBridge 示例:

#import  

@interface H5WebViewController ()
@property (strong, nonatomic) WKWebView *webView;
@property WKWebViewJavascriptBridge *bridge;

@end

- (void)viewDidLoad {
    [super viewDidLoad];

    [self setUpWebView];
    [self setUpWebViewJavascriptBridge];
}

- (void)setUpWebView {
    self.wkWebView = [[WKWebView alloc] initWithFrame:self.view.bounds];
    self.wkWebView.navigationDelegate = self;
    self.wkWebView.UIDelegate = self;
    [self.view addSubview:self.wkWebView];
}

/**
 * 使用 WebViewJavascriptBridge 实现 OC 与 JS 交互
 */
- (void)setUpWebViewJavascriptBridge {
    if (_bridge) {
        return;
    }
    
    // 设置能够进行桥接
    [WebViewJavascriptBridge enableLogging];
    
    // 初始化 WebViewJavascriptBridge 实例, 设置代理, 进行桥接
    _bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView];
    [_bridge setWebViewDelegate:self];
    
    
    __weak __typeof(self)weakSelf = self;

    /**
     JS 调用 OC ,设置导航条 title
     
     @param data 后台 JS 页面传过来的参数
     @param registerHandler 要注册的事件名称(这里我们为 locationAlertViewWithMessage)
     @param handler 回调 block 函数 当后台触发这个事件的时候会执行 block 里面的代码
     */
    [_bridge registerHandler:@"_app_setTitle" handler:^(id data, WVJBResponseCallback responseCallback) {
        if (data) {
            NSDictionary *dic = (NSDictionary *)data;
            weakSelf.title = dic[@"title"];
        }
        // responseCallback 给后台 JS 的回复
        responseCallback(@"OK,已收到标题信息!");
    }];
    
    /**
     * JS 调用 OC ,关闭当前 H5 控制器
     */
    [_bridge registerHandler:@"_app_closeWebView" handler:^(id data, WVJBResponseCallback responseCallback) {
        [weakSelf closeTheView];
        responseCallback(@"OK,已关闭当前 WebView ");
    }];
    

    /**
     * OC 调用 JS ,获取 OC 的值
     */
    [_bridge callHandler:@"_app_getToken" data:@"userToken"];
}

- (void)dealloc {
    [_bridge removeHandler:@"_app_setTitle"];
    [_bridge removeHandler:@"_app_closeWebView"];
    [_bridge removeHandler:@"_app_getToken"]; 
}

// 关闭当前窗口
- (void)closeTheView { 
    [self dismissViewControllerAnimated:YES completion:nil];
    [self.navigationController popViewControllerAnimated:YES];
}

3、HTML 代码:




    
    
    
    
    Document


    
js调用oc

结束语

WebViewJavascriptBridge 使用起来比较方便快捷,并且还有 Android 版本的。如果 Android 和 iOS 都使用的话,就避免了前端既要写一份 Android 又要写一份 iOS 的 JS 与 OC 交互,调试起来只要一端通了,JS 那边应该就没啥问题,排查问题方便、高效,不用针对两个端分别设置不同的代码,统一性很重要哦。

如有不足,欢迎批评指正!

你可能感兴趣的:(iOS 开发之 OC 与 JS 的通信桥梁:WebViewJavascriptBridge)