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

原理:利用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
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值