WKWebView和H5交互的两种方法

966 阅读2分钟

一、使用WKScriptMessageHandler

1.初始化WKWebView并注入JS调用的方法

//使用添加了ScriptMessageHandler的userContentController配置configuration
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
WKUserContentController *userContentController = [[WKUserContentController alloc] init];
//注入方法
[userContentController addScriptMessageHandler:self name:@"openNativeAlert"]; 
configuration.userContentController = userContentController;
    
//初始化
_WKWebView = [[WKWebView alloc]initWithFrame:self.view.frame configuration:configuration];
_WKWebView.UIDelegate = self;
_WKWebView.navigationDelegate = self;
_WKWebView.scrollView.delegate = self;
// 这行代码可以是侧滑返回webView的上一级,而不是根控制器(*只针对侧滑有效)
[_WKWebView setAllowsBackForwardNavigationGestures:true];
if(@available(iOS 11.0, *)) {
    _WKWebView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
[self.view addSubview:_WKWebView];

2.点击js按钮调用oc方法

//oc代码
//实现 WKScriptMessageHandler 协议方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    if ([message.name isEqualToString:@"openNativeAlert"]){
        NSLog(@"js调用了我")
    }
}



//js代码
send() {
   var params = {
	    title: 'JS调用Native弹框',
   }
   let data = JSON.stringify(params)

   if (port == 'android') {
		window.testInterface.openNativeAlert(data);
   } else if (port == 'ios') {
		window.webkit.messageHandlers.openNativeAlert.postMessage(data);
   }
}

3.点击oc按钮调用js方法

//oc代码
- (void)hanldBtn
{
    NSString * function = [NSString stringWithFormat:@"openJsAlert(\"%@\")",@"native调用js"];
    //执行js方法
    [self.WKWebView evaluateJavaScript:function completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        //回调 error==nil 就是调用成功
        NSLog(@"error = %@",error);
    }];
}


//js代码
mounted() {
	window.openJsAlert = this.openJsAlert;
},
openJsAlert(data) {
   alert(data)
}

二、使用WKWebViewJavascriptBridge

1.引入WKWebViewJavascriptBridge初始化WKWebView

#import "WKWebViewJavascriptBridge.h"

/**jsBridge*/
@property (nonatomic, strong) WKWebViewJavascriptBridge* bridge;


//初始化
_WKWebView = [[WKWebView alloc]initWithFrame:self.view.frame];
_WKWebView.UIDelegate = self;
_WKWebView.navigationDelegate = self;
_WKWebView.scrollView.delegate = self;
// 这行代码可以是侧滑返回webView的上一级,而不是根控制器(*只针对侧滑有效)
[_WKWebView setAllowsBackForwardNavigationGestures:true];
if(@available(iOS 11.0, *)) {
   _WKWebView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
[self.view addSubview:_WKWebView];



  //初始化
[WKWebViewJavascriptBridge enableLogging];
//连接webView
_bridge = [WKWebViewJavascriptBridge bridgeForWebView:_WKWebView];
//设置代理
[_bridge setWebViewDelegate:self];

2.创建bridge.js

//js代码
/* eslint-disable */
// 根据navigator.userAgent判断一下当前环境属于ios环境还是按住哦环境
let isAndroid =
  navigator.userAgent.indexOf("Android") > -1 ||
  navigator.userAgent.indexOf("Adr") > -1;
let isiOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);

/** 针对安卓和ios系统,对window.WebViewJavascriptBridge进行兼容性处理 */
//这是必须要写的,用来创建一些设置
function setupWebViewJavascriptBridge(callback) {
  //Android使用
  if (isAndroid) {
    if (window.WebViewJavascriptBridge) {
      callback(WebViewJavascriptBridge);
    } else {
      //添加dom事件
      document.addEventListener(
        "WebViewJavascriptBridgeReady",
        function() {
          callback(WebViewJavascriptBridge);
        },
        false
      );
    }
    sessionStorage.phoneType = "android";
  }

  //iOS使用
  if (isiOS) {
    if (window.WebViewJavascriptBridge) {
      return callback(WebViewJavascriptBridge);
    }
    if (window.WVJBCallbacks) {
      return window.WVJBCallbacks.push(callback);
    }
    window.WVJBCallbacks = [callback];
    var WVJBIframe = document.createElement("iframe");
    WVJBIframe.style.display = "none";
    WVJBIframe.src = "wvjbscheme://__BRIDGE_LOADED__";
    document.documentElement.appendChild(WVJBIframe);
    setTimeout(function() {
      document.documentElement.removeChild(WVJBIframe);
    }, 0);
    sessionStorage.phoneType = "ios";
  }
}
//注册回调函数,第一次连接时调用 初始化函数(android需要初始化,ios不用)
setupWebViewJavascriptBridge(function(bridge) {
  if (isAndroid) {
    //初始化
    bridge.init(function(message, responseCallback) {
      var data = {
        "Javascript Responds": "Wee!"
      };
      responseCallback(data);
    });
  }
});

export default {
  // js调APP方法 (参数分别为:app提供的方法名  传给app的数据  回调)
  callHandler(name, data, callback) {
    setupWebViewJavascriptBridge(function(bridge) {
      bridge.callHandler(name, data, callback);
    });
  },
  // APP调js方法 (参数分别为:js提供的方法名  回调)
  registerHandler(name, callback) {
    setupWebViewJavascriptBridge(function(bridge) {
      bridge.registerHandler(name, function(data, responseCallback) {
        callback(data, responseCallback);
      });
    });
  }
};

3.全局注册bridge.js

import Bridge from './bridge.js'
Vue.prototype.$bridge = Bridge

4.点击js按钮调用oc方法

oc代码
//注册api
- (void)registerApi
{
    [_bridge registerHandler:@"openNativeAlert" handler:^(id data, WVJBResponseCallback responseCallback){
        NSLog(@"js调用了我%@",data);
    }];
}


//js代码
send() {
    let temp = {
		title: 'JS调用Native弹框',
	}
	this.$bridge.callHandler('openNativeAlert', temp, function(responseData) {
		console.log("callback: ", responseData)
    });
}

5.点击oc按钮调用js方法

//oc代码
- (void)hanldBtn
{
    NSDictionary * dic = @{@"title":@"native调用js"};
    [_bridge callHandler:@"openJsAlert" data:dic];
}

//js代码
onLoad() {
   this.registerApi()
},
registerApi() {
	//app调用js方法
	this.$bridge.registerHandler('openJsAlert', function(responseData) {
         console.log("callback: ", responseData)
		 alert(responseData.title)
    });
},