Hybird开发WebViewiOS点点滴滴

OC和JS交互(WKWebView)入门篇

2017-11-25  本文已影响40人  bigParis

在iOS8.0, 苹果推出了WebKit框架, 但时至今日, 仍然有很多公司需要支持iOS8以下的系统, 所以可能还没有将UIWebView完全更换成WKWebView, WKWebView的性能上的表现确实比UIWebView好很多, 但是坑也很多, 要用WKWebView就要接受它的坑.

前面的一些列文章着重讲述了UIWebView和JS的交互, 下面是参考链接

OC和JS交互(UIWebView)入门篇
OC和JS交互(UIWebView)中级篇1
OC和JS交互(UIWebView)中级篇2
OC和JS交互(UIWebView)中级篇3

WKWebView和UIWebView一样, 在和JS交互的时候也可以通过JS注入的方式, 而且在WebViewJavaScriptBridge框架中也提供了对WKWebView的支持. 这里只对和UIWebView不同的地方进行说明.

- (void)webView:(WKWebView *)webView
decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    if (webView != _webView) { return; }
    NSURL *url = navigationAction.request.URL;
    __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate;

    if ([_base isCorrectProcotocolScheme:url]) {
        if ([_base isBridgeLoadedURL:url]) {
            [_base injectJavascriptFile];
        } else if ([_base isQueueMessageURL:url]) {
            [self WKFlushMessageQueue];
        } else {
            [_base logUnkownMessage:url];
        }
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    
    if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:decisionHandler:)]) {
        [_webViewDelegate webView:webView decidePolicyForNavigationAction:navigationAction decisionHandler:decisionHandler];
    } else {
        decisionHandler(WKNavigationActionPolicyAllow);
    }
}

上面的代码是WKWebView的代理方法, 当改变网页的src属性, 就会触发这个代理被调用, 和UIWebView- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType类似, 这里需要注意一点, 要确保- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler代理一定调用到decisionHandler否则会崩溃, 而且不能重复调用, 这里原著应该是有个bug的.

if ([_base isCorrectProcotocolScheme:url]) {
        if ([_base isBridgeLoadedURL:url]) {
            [_base injectJavascriptFile];
        } else if ([_base isQueueMessageURL:url]) {
            [self WKFlushMessageQueue];
        } else {
            [_base logUnkownMessage:url];
        }
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }

上面的if分支一定要return, 否则会崩溃

'NSInternalInconsistencyException', reason: 'Completion handler passed to -[WKWebViewJavascriptBridge webView:decidePolicyForNavigationAction:decisionHandler:] was called more than once'

信息已经说的很明白了, 多次调用decisionHandler.
这里对于OC和JS交互(UIWebView)中级篇3
中最后遗留的3个问题的第二个实际已经有了答案, 对于WKWebView依然可以进行拦截. 至于其它2个问题, 我们将会在后面的文章陆续给出答案.

上一篇下一篇

猜你喜欢

热点阅读