1.webView控件实例(UIWebView/WKWebView)引入前web端资源元素。

2.HybridApp客户端原生与web前端交互(OC语言&JS语言 交互)

3.Hybrid交互的方式3种:(1)单纯借助系统自带的框架模块比如:UIWebView借助自带的JavaScriptCore框架模块的API实现交互;WKWebView借助自带的WKUserContentController框架模块的API实现交互。

4.左侧成员名的层次结构模型包容右边堆区实例的层次结构模型。托管者的层次结构模型应该包容被托管者的层次结构模型(多太现象)。

5.valueforKeyPath采用KVC模式,键值路径中每个.路径对应堆区实例域中的次级字段名。

6.内嵌控件的渲染->交互的特性配置->数据载入->交互动作

7.来自于前web端的元素组(控)件即webView视图上内嵌的非原生元素控件(h5前端调用原生API);普通原生控件(原生调用h5前端API)

8.原生端和h5前端的混合编写(HybridApp)可以分为2个阶段:界面渲染阶段(内嵌控件+数据载入)+动作交互阶段(交互配置+交互动作)

9.界面视觉渲染阶段:由webView实例本身决定不受交互的框架模块选择影响。

动作交互阶段:界面视觉渲染完成之后进入动作交互阶段,根据webView实例的类型可选择UIWebView自带的javaScriptCore框架模块的API实现交互/WKWebView自带的WKUserContentController框架模块的API实现交互/三方框架WebViewJavaScriptBridge框架模块的API实现交互

原理机制:

1.UIWebView采用系统自带的JavaScriptCore框架模块的API实现交互:

iOS 与H5交互失效 h5和客户端交互_API

原生端构建文件单元WebViewController和JSCoreObject。h5前端领导->

助理JSCoreObject(WebViewController的领导)->WebViewController助理。此处2层代理协议迭代。

jsContext?.evaluateScript(原生调用h5前端API)
 let context = webView.value(forKeyPath:
 “documentView.webView.mainFrame.javaScriptContext”) as! JSContext
jsContext.exceptionHandler = ^(JSContext *context, JSValue *exception) {
 NSLog(@“%@”,@“获取 WebView JS 执行环境失败了!”);
 }

2.WKWebView采用系统自带的WKUserContentController框架模块的API实现交互:
通过userContentController注册原生的函数实例API
[webView.configuration.userContentController addScriptMessageHandler:self name:@“ocFunc”];
OC原生端遵守WKScriptMessageHandler协议

  • (void)userContentController:(WKUserContentController )userContentController didReceiveScriptMessage:(WKScriptMessage )message
    //重要点
    3.WKWebView&UIWebView采用三方框架WebViewJavaScriptBridge框架模块的API实现交互:
    基本原理:
    (OC)原生端指令:原生函数API注入jsBridge桥+原生调用前端API
    (JS)h5前端指令:前端函数API注入jsBridge桥+h5前端调用原生API

    iOS 与H5交互失效 h5和客户端交互_hybrid_02

    (OC)原生端指令构建(关键点):
    1.pod ‘WebViewJavascriptBridge’ //项目导入三方框架WebViewJavaScriptBridge
    2.WebViewController文件单元內导入头文件
    *#import “WebViewJavascriptBridge.h”*** 3.构建jsBridge桥实例
self.jsBridge = [WebViewJavascriptBridge bridgeForWebView:self.baseWebView webViewDelegate:self handler:^(id data, WVJBResponseCallback responseCallback) {
 }];//self.baseWebView内嵌的webView网图实例(webViewDelegate)
  • 4.往jsBridge桥中注入原生函数API
[self.jsBridge registerHandler:@“TemporaryTorageData” handler:^(id data, WVJBResponseCallback responseCallback) {
 NSLog(@“dataFromJSh5前端: %@”,data[@“data”]);//data来自JSh5前端
 alert(“OC被JS调用了.”);
 responseCallback(@“responseData扫描结果 : www.baidu.com”);//responseData入参数据来自0C
 }];
 //TemporaryTorageData是原生函数API的别名
 //原生函数API本身实例区由h5前端调用
 //此时data托管持有的实例由h5前端提供数据
 //此时responseCallback:原生的函数API本身被h5前端调用执行完毕后,h5前端会提供回调块block(responseCallback:把原生端oc中的数据@"扫描结果 : www.baidu.com"传递给h5前端区)
  • 5.通过***[_jsBridge callHandler:@“PasswordChanged” data:@“把HTML的背景颜色改成橙色!!!”];***//原生调用h5前端函数API 6.原生oc端的WebViewController文件单元的viewDidDisappear函数内
• - (void)viewDidDisappear:(BOOL)animated {
 [super viewDidDisappear:animated];
 [_jsBridge removeHandler:@“原生函数API”];//防止WebViewController控制器不释放
 [_jsBridge removeHandler:@“原生函数API”];
 }//handler:处理程序

(JS)h5前端指令构建(不关注):
1.function setupWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
window.WVJBCallbacks = [callback]; // 创建一个 WVJBCallbacks 全局属性数组,并将 callback 插入到数组中。
var WVJBIframe = document.createElement(‘iframe’); // 创建一个 iframe 元素
WVJBIframe.style.display = ‘none’; // 不显示
WVJBIframe.src = ‘wvjbscheme://BRIDGE_LOADED’; // 设置 iframe 的 src 属性
document.documentElement.appendChild(WVJBIframe); // 把 iframe 添加到当前文导航上。
setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
}
2.往jsBridge桥中注入h5前端API(JS函数:jsFunction)
setupWebViewJavascriptBridge(function(bridge){
// 声明 OC 需要调用的 JS 方法。
bridge.registerHanlder(‘testJavaScriptFunction’,function(data,responseCallback){
document.body.style.backgroundColor = “orange”;
document.getElementById(“returnValue”).value = data;
alert(“JS被OC调用了.”);
nslog(@“%@”,data);//data来自0C
responseCallback(@“responseData来自js的数据”);//responseData入参数据来自JS前端

})
});
//testJavaScriptFunction是h5前端函数API的别名
//h5前端函数API本身实例区由原生端调用
//此时data托管持有的实例由原生端提供数据
//此时responseCallback:h5前端的函数API本身被原生端调用执行完毕后,原生端会提供回调块block(responseCallback:把h5前端中的数据{data: "js 的数据",from : "JS"}传递给原生oc区)
3.
通过WebViewJavascriptBridge.callHandler('TemporaryTorageData',function(dataFromOC) {
        alert("h5前端调用原生函数API");
        document.getElementById("returnValue").value = dataFromOC;
    })

补充说明部分:
OC原生调用h5前端API-》3种方式:
//调用JSFunction,不向JS前端传递信息数据,也不需要前端JSFunction中的responseCallback传递数据至OC原生。
[_jsBridge callHandler:@“h5前端API别名”];
//调用JSFunction,向JS前端传递信息数据,但不需要前端JSFunction中的responseCallback传递数据至OC原生。
[_jsBridge callHandler:@“h5前端API别名” data:@“来自于oc的某个数据”];
//调用JSFunction,向JS前端传递信息数据,也需要前端JSFunction中的responseCallback传递数据至OC原生。
[_jsBridge callHandler:@“h5前端API别名” data:@“来自于oc的某个数据” responseCallback:^(id responseData) {
NSLog(@“JS的返回值: %@”,responseData);//responseData入参数据来自JS前端
}];

h5前端调用OC原生函数API-》3种方式:
// 调用OCFunction,不向OC原生端传递信息数据,也不需要原生端OCFunction中的responseCallback传递数据至JSh5前端。

WebViewJavascriptBridge.callHandler(‘原生端函数API别名’);

// 调用OCFunction,向OC原生端传递信息数据但不需要原生端OCFunction中的responseCallback传递数据至JSh5前端。
WebViewJavascriptBridge.callHandler(‘原生端函数API别名’,“来自于js前端的数据”);

//调用OCFunction,向OC原生端传递信息数据,需要原生端OCFunction中的responseCallback传递数据至JSh5前端。
WebViewJavascriptBridge.callHandler(‘原生端函数API别名’,{data : “来自于js前端的数据”},function(dataFromOC){
alert(“JS前端调用OC原生API方法”);
nslog(@“%@”,dataFromOC);//dataFromOC:来自于OC原生端的数据
document.getElementById(“returnValue”).value = dataFromOC;
});

最后总结:
1.UIWebView&JavaScriptCore系统自带的JS&OC交互方案。
2.WKWebView&userContentController系统自带的JS&OC交互方案。
3.WebViewJavascriptBridge可搭配UIWebView&WKWebView基于三方框架实现OC&JS交互。
4.WebViewJavascriptBridge原理:(OC)原生端指令:原生函数API注入jsBridge桥+原生调用前端API
(JS)h5前端指令:前端函数API注入jsBridge桥+h5前端调用原生API