之前做过一些 H5 和 iOS 原生交互的相关工作,在这里做下总结。
H5 和 iOS 原生交互现在主流的有两种方式:
- 通过 Webview 拦截 url 请求和 Webview 的执行 js 方法来实现
- 通过 JavaScriptCore 来实现
目前用的比较多的方式是第一种,一方面是因为 JavaScriptCore 是 iOS7 之后才出现的,另一方面也因为 WebViewJavascriptBridge 这个框架,它是采用第一种方式实现的,而且封装的也比较好。
拦截请求方式
原生调用 H5
原生调用 H5 比较简单,直接调用 UIWebView(WKWebView 同理)当中的
1 | - (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script; |
方法即可。同时 WKWebView 当中还增加了一个异步调用的方法
1 | - (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ __nullable)(__nullable id, NSError * __nullable error))completionHandler; |
H5 调用原生
H5 调用原生通过在 UIWebView(WKWebView 同理)的
1 | - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType; |
方法中拦截请求的 url,通过 url 携带的信息调用相关原生方法。(实例代码来源:WebViewJavascriptBridge)
1 | - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { |
以上代码通过 isCorrectProcotocolScheme:、isBridgeLoadedURL:和 isQueueMessageURL:三个方法对拦截的 url 进行判断需要执行哪个原生的方法。
一些 H5 和原生的交互的比较简单的使用将参数拼在 url 中,在 url 拦截时将 url 截取获得相关参数。而 WebViewJavascriptBridge 则是将需要获取的数据放到 js 对象当中,让原生通过[self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]]调用 js 去取到数据。
JavaScriptCore 方式
JavaScriptCore 是 iOS7 之后添加的库,这个库使 H5 和原生的交互变得比较简单。
原生调用 H5
1 | JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; |
H5 调用原生
JavaScriptCore 方式 H5 和原生交互更像是将一个原生对象注册到 H5 的 js 当中,通过 js 来调用。
js 直接调用方法
1 | - (void)webViewDidFinishLoad:(UIWebView *)webView |
js 通过对象调用方法,此时需要向 js 当中传递一个实现了 JSExport 协议的对象,通过该对象调用在协议中声明并实现的自定义方法。
1 | 创建一个继承JSExport协议的协议,并添加自定义方法 |
在 js 当中调用时需要注意当调用多个参数的方法时需要需要将方法名拼接起来调用,比如我们写的两个参数调用就需要写成 testJS.testOnetwo(‘参数 1’,’参数 2’),如下:
1 | //我们模拟一下H5当中的js调用 |