WK的基本用法先不说了,主要在这里记录一下使用WKWebView在于H5交互时走过的一些坑,以及如果web端的同学如果没有做过和ios端的交互,那么自己也可以去帮助web端去完成;另外在调试过程中,也不用一味的去等待和H5去联调,可以自己写一个本地的链接供自己去提前调试
这里主要写js调用OC的两种场景
首先需要和H5端去定义一些协议,来完成不同的功能,例如:在app的H5界面,进入OC的某个界面;H5端需要动态的获取OC的一些参数等
第一种场景:
举一个H5界面需要调用app分享的例子,分享的过程中可以给app传递一些参数, 首先定义一个公共的协议名称 ‘shareByApp’
js的代码就非常简单了,只需要在方法中这样去写就可以了
window.webkit.messageHandlers.定义的方法名(shareByApp).postMessage(参数)
第一个坑:
参数如果不需要刻意不传,但是如果传对象类型的,这就需要和安卓端的有所不同了,这里写的key是不需要加双引号的,只有value需要加单引号,否则在app端是接收不到正确的数据的,下面是正确写法
window.webkit.messageHandlers.shareByApp.postMessage({shareType:'1',shareUrl:'http://www.baidu.com',shareTitle:'我是分享的标题',shareDesc:'我是分享的描述',shareImgUrl:'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1526379795&di=3ceb1bdfa94f3148d4d54cd24a6ae2f6&imgtype=jpg&er=1&src=http%3A%2F%2Ftupian.aladd.net%2F2015%2F9%2F228.jpg'})
app端需要实现的代码:
WKUserContentController* userContent = [[WKUserContentController alloc] init];
//首先添加消息处理,注意:self指代的对象需要遵守WKScriptMessageHandler协议,结束时需要移除
[userContent addScriptMessageHandler:self name:@"shareByApp"];
//然后将将UserConttentController设置到配置文件
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
configuration.userContentController = userContent
移除的方法
[self.webview.configuration.userContentController removeScriptMessageHandlerForName:@"shareByApp"];
然后,只要H5端触发这段代码,就可以在WKScriptMessageHandler下面这个代理方法中捕捉到了
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
//有时可能需要调用很多app的方法,所以根据message.name来区分执行不同的方法。message.body中传过来的就是在js中写好的参数
//进行name判断,就可以写指定的方法了
}
第二种场景:
有些时候,H5界面某些交互可能需要判断app是否登录了,这就需要js主动去掉OC的方法,并且将app的一些信息传递回去,首先还是指定一个协议 ‘isLoginApp’
然后WKWebView需要导入一个文件(WebViewJavascriptBridge),下载链接
然后需要在js里面注入一部分代码,用于初始化
放到需要调用OC方法的js文件中就可以
function setupWebViewJavascriptBridge(callback) {
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 = 'https://__bridge_loaded__';
document.documentElement.appendChild(WVJBIframe);
setTimeout(function () {
document.documentElement.removeChild(WVJBIframe)
}, 0)
}
然后再去实现这个方法
function processIosGetCoupon() {
WebViewJavascriptBridge.callHandler('isLoginApp', null, function (response) {
//response就是从app端返回的参数
})
}
OC的代码实现:
//导入头文件后初始化
self.webViewBridge = [WKWebViewJavascriptBridge bridgeForWebView:self.webview];
[self.webViewBridge setWebViewDelegate:self];
//然后将需要传入的参数放入这个block中
[_webViewBridge registerHandler:@"isLoginApp" handler:^(id data, WVJBResponseCallback responseCallback) {
// 将需要的参数传给js
responseCallback(@"已登录/未登录");
}];
第二个坑:这里的问题主要在于,H5中的将注入上面代码的js文件放进去,app端调用web的URL后面如果拼接任何参数,一定得保证新的url中一定含有注入上面代码的js文件,否则界面上看不出任何问题,但是就是进入不到OC代码的回调里,这里一定得注意