原生JS交互(二)—— WKWebView拦截URL

系列

原生JS交互(一)—— UIWebView拦截URL

一、前言

  • 上一章我们讲述了通过UIWebView拦截URL,以及调用JS的Function,在原生方面与JS方面的实现。
  • 本章我们说一下WKWebView拦截URL在原生方面的实现。

UIWebView与WKWebView比较
1. 因为UIWebView会导致内存问题,所以建议开发者还是使用WKWebView加载H5页面
2. 同时WKWebView可以很容易地实现H5页面加载进度
3. WKWebView不能弹出前端的alert,需在代理方法中弹出原生alertController

  • 无论是WKWebView还是UIWebView,通过拦截URL的方式实现JS交互,JS的实现都是一样的原理,所以本章就不说了。
  • 先再贴一下上章的前端代码,与上一章的前端代码完全一致。



    
    拦截url
    






二、WKWebView加载HTML

WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
configuration.userContentController = [[WKUserContentController alloc] init];
WKPreferences *preferences = [[WKPreferences alloc] init];
preferences.javaScriptCanOpenWindowsAutomatically = YES;
preferences.minimumFontSize = 30.0;
configuration.preferences = preferences;
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
webView.UIDelegate = self;
webView.navigationDelegate = self;
[self.view addSubview:webView];
self.webView = webView;

三、WKWebView的UIDelegate与navigationDelegate

  • UIDelegate,即WKUIDelegate协议代理对象。
    常用的协议方法如下:
// webView关闭调用
- (void)webViewDidClose:(WKWebView *)webView
{
    
}

// WKWebView不能弹出alert,需要用原生alertController,其中message参数就是前端alert function中的参数
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
    UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"哈哈" message:message preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"NO" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
    }];
    [alertVC addAction:cancelAction];
    [self presentViewController:alertVC animated:YES completion:nil];
}
  • navigationDelegate,即WKNavigationDelegate协议代理对象。
    我们常用的协议方法如下:
// 类似于UIWebView中拦截URL的代理方法,要注意的是decisionHandler不能连续回调两次,否则会引起crash
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    decisionHandler(WKNavigationActionPolicyAllow);
}

// H5页面开始加载回调方法
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation
{
    
}

// H5页面正在加载回调方法
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation
{
    
}

// H5页面结束加载回调方法
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error
{
    
}

// H5页面加载失败回调方法
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
    
}

四、WKWebView监听前端页面加载进度

使用KVO,监听WKWebView对象的estimatedProgress属性

// KVO设置observer
[self.webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];

// 监听回执
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([object isEqual:self] && [keyPath isEqualToString:@"webView.estimatedProgress"])
    {
        [self.progressView setProgress:self.webView.estimatedProgress animated:YES];
        if (self.progressView.progress == 1.0)
        {
             self.progressView.hidden = YES;
        }
    }
}

五、WKWebView拦截URL

使用上面已经提到的WKNavigationDelegate的协议方法。

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    NSString *urlStr = navigationAction.request.URL.absoluteString;
    if ([urlStr rangeOfString:@"mamami://click"].length > 0)
    {
        decisionHandler(WKNavigationActionPolicyCancel);
    } else {
        decisionHandler(WKNavigationActionPolicyAllow);
    }
}

六、WKWebView调用JS

再次提醒前端,原生需要调用的function写在window下,别那么自信全局function与window下的function没有区别。

NSString *jsStr = [NSString stringWithFormat:@"ocInvoke('%@','%@')", @"我", @"是"];
[self.webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable data, NSError * _Nullable error) {
     NSLog(@"%@-%@", data, error);
}];

要注意一点,如果js调用了系统的alert function,原生使用WKWebView加载时,必须实现runJavaScriptAlertPanelWithMessage 协议方法,使用原生alertController进行弹窗。否则会造成crash

最后

在新工作相对屌丝,相对安逸的情况下。希望自己能不忘初心,脚踏实地

你可能感兴趣的:(原生JS交互(二)—— WKWebView拦截URL)