ios与H5通过WKWebView交互详解

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代码的回调里,这里一定得注意

展开阅读全文

没有更多推荐了,返回首页