OC与JS交互方法(一)拦截URL

来源:互联网 发布:物流优化精确算法 编辑:程序博客网 时间:2024/06/03 20:22

原理:利用webview的代理方法(shouldStartLoadWithRequest),拦截即将加载的URL,再通过scheme区分点击事件类型。

先看看html页面的JS代码

function loadURL(url) {                    var iFrame;                    iFrame = document.createElement("iframe");                    iFrame.setAttribute("src", url);                    iFrame.setAttribute("style", "display:none;");                    iFrame.setAttribute("height", "0px");                    iFrame.setAttribute("width", "0px");                    iFrame.setAttribute("frameborder", "0");                    document.body.appendChild(iFrame);                    // 发起请求后这个iFrame就没用了,所以把它从dom上移除掉                    iFrame.parentNode.removeChild(iFrame);                    iFrame = null;}function scanClick() {                alert(arr);                //页面响应点击事件后使用iFrame的scr加载url,会被uiwebview的代理方法拦截                loadURL("haleyAction://scanClick");}function shareClick() {                    loadURL("haleyAction://shareClick?title=测试分享的标题&content=测试分享的内容&url=http://www.baidu.com");}function locationClick() {                loadURL("haleyAction://getLocation");}function setLocation(location) {                    //stringByEvaluatingJavaScriptFromString是一个同步方法,会等待js 方法执行完成,而弹出的alert 也会阻塞界面等待用户响应,所以他们可能会造成死锁。导致alert 卡死界面。如果回调的JS 是一个耗时的操作,那么建议将耗时的操作也放入setTimeout的function 中                asyncAlert(location);                document.getElementById("returnValue").value = location;}function asyncAlert(content) {                setTimeout(function(){                           alert(content);                           },1);}

JS搞定了,那么下一步就是OC的操作了

主要用到-stringByEvaluatingJavaScriptFromString和webview的代理方法:-shouldStartLoadWithRequest

-stringByEvaluatingJavaScriptFromString——这个方法传入的就是JavaScript代码,直接在UIWebView上面执行js方法。

WKWebview中拦截URL的方法

与uiwebview不同之处:

  1. 初始化多了个configuration参数。
  2. WKWebView的代理有两个navigationDelegate和UIDelegate。我们要拦截URL,就要通过navigationDelegate的一个代理方法来实现。如果在HTML中要使用alert等弹窗,就必须得实现UIDelegate的相应代理方法。
  3. WKWebView的代理有两个navigationDelegate和UIDelegate。我们要拦截URL,就要通过navigationDelegate的一个代理方法来实现。如果在HTML中要使用alert等弹窗,就必须得实现UIDelegate的相应代理方法

初始化wkwebview方法

    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];    configuration.userContentController = [WKUserContentController new];    WKPreferences *preferences = [WKPreferences new];    preferences.javaScriptCanOpenWindowsAutomatically = YES;    preferences.minimumFontSize = 30.0;    configuration.preferences = preferences;    self.webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];    NSString *urlStr = [[NSBundle mainBundle] pathForResource:@"index.html" ofType:nil];    NSURL *fileURL = [NSURL fileURLWithPath:urlStr];    [self.webView loadFileURL:fileURL allowingReadAccessToURL:fileURL];    self.webView.navigationDelegate = self;    [self.view addSubview:self.webView];

拦截URL

使用WKNavigationDelegate中的代理方法,拦截自定义的URL来实现JS调用OC方法:

#pragma mark - WKNavigationDelegate- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler//如果实现了这个代理方法,就必须得调用decisionHandler这个block{    NSURL *URL = navigationAction.request.URL;    NSString *scheme = [URL scheme];    //uiwebview和wk都需要统一的scheme;    if ([scheme isEqualToString:@"scheme"]) {        [self handleCustomAction:URL];        //WKNavigationActionPolicyCancel代表取消加载等于是return NO;        decisionHandler(WKNavigationActionPolicyCancel);        return;    }    //WKNavigationActionPolicyAllow代表允许加载;    decisionHandler(WKNavigationActionPolicyAllow);}

调用JS:

WKWebView 提供了一个新的方法evaluateJavaScript:completionHandler:,实现OC 调用JS 等场景。功能与stringByEvaluatingJavaScriptFromString类似。

WKWebView中使用alert:

在上面提到,如果在WKWebView中使用alert、confirm 等弹窗,就得实现WKWebView的WKUIDelegate中相应的代理方法。
例如,我在JS中要显示alert 弹窗,就必须实现如下代理方法,否则alert 并不会弹出。

pragma mark - WKUIDelegate (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提醒" message:message preferredStyle:UIAlertControllerStyleAlert];    [alert addAction:[UIAlertAction actionWithTitle:@"知道了" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {    //这个block 一定得调用,至于在哪里调用,倒是无所谓,我们也可以写在方法实现的第一行,或者最后一行        completionHandler();    }]];    [self presentViewController:alert animated:YES completion:nil];}
0 0
原创粉丝点击