在上篇文章中讲述了使用UIWebView拦截URL的方式来处理JS与OC交互。

由于UIWebView比较耗内存,性能上不太好,而苹果在iOS 8中推出了WKWebView。

同样的用WKWebView也可以拦截URL,做JS 与OC交互。关于WKWebView与UIWebView的对比,大家请自动百度或者google。

打开百度网页前 打开百度网页后
UIWebView 内存47M
WKWebView 内存47M

WKWebView 拦截URL

WKWebView 与 UIWebView 拦截URL 的处理方式基本一样。除了代理方法和WKWebView的使用不太一样,关于WKWebView更详尽的讲解和用法,还是自行搜索学习,本文重点还是讲解如何实现JS 与OC 互相调用。

提醒:WKWebView 是iOS 8 推出的WebKit.framework中的控件,只有app 不需要兼容iOS 7及以下的时候才可以使用。

先看动态效果图:

1.创建WKWebView,加载本地HTML。

WKWebView的创建有几点不同:

* 1.初始化多了个configuration参数,当然这个参数我们也可以不传,直接使用默认的设置就好。

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

* 3.在iOS 9之前,WKWebView加载本地HTML会有一些问题。(不能加载本地HTML,或者部分CSS/本地图片加载不了等)

我这里创建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];

因为加载的本地HTML内容,跟上一篇UIWebView中介绍的HTML内容一样,所以关于HTML中的内容就不再讲解了。

2.拦截URL

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

#pragma mark - WKNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    NSURL *URL = navigationAction.request.URL;
    NSString *scheme = [URL scheme];
    if ([scheme isEqualToString:@"haleyaction"]) {
        [self handleCustomAction:URL];
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}

需要注意的是:

1.如果实现了这个代理方法,就必须得调用decisionHandler这个block,否则会导致app 崩溃。block参数是个枚举类型,WKNavigationActionPolicyCancel代表取消加载,相当于UIWebView的代理方法return NO的情况;WKNavigationActionPolicyAllow代表允许加载,相当于UIWebView的代理方法中 return YES的情况。

2.其他的关于为什么要统一设置scheme,在上一篇中讲过。

关于如何区分执行不同的OC 方法,也与UIWebView的处理方式一样,通过URL 的host 来区分执行不同的方法:

#pragma mark - private method
- (void)handleCustomAction:(NSURL *)URL
{
    NSString *host = [URL host];
    if ([host isEqualToString:@"scanClick"]) {
        NSLog(@"扫一扫");
    } else if ([host isEqualToString:@"shareClick"]) {
        [self share:URL];
    } else if ([host isEqualToString:@"getLocation"]) {
        [self getLocation];
    } else if ([host isEqualToString:@"setColor"]) {
        [self changeBGColor:URL];
    } else if ([host isEqualToString:@"payAction"]) {
        [self payAction:URL];
    } else if ([host isEqualToString:@"shake"]) {
        [self shakeAction];
    } else if ([host isEqualToString:@"goBack"]) {
        [self goBack];
    }
}

3.OC 调用 JS 方法

JS 调用OC 方法后,有的操作可能需要将结果返回给JS。这时候就是OC 调用JS 方法的场景。

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

- (void)getLocation
{
    // 获取位置信息
    
    // 将结果返回给js
    NSString *jsStr = [NSString stringWithFormat:@"setLocation('%@')",@"广东省深圳市南山区学府路XXXX号"];
    [self.webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        NSLog(@"%@----%@",result, error);
    }];
}

evaluateJavaScript:completionHandler:没有返回值,JS 执行成功还是失败会在completionHandler 中返回。所以使用这个API 就可以避免执行耗时的JS,或者alert 导致界面卡住的问题。

4.WKWebView中使用弹窗

在上面提到,如果在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) {
        completionHandler();
    }]];
    
    [self presentViewController:alert animated:YES completion:nil];
}

其中completionHandler这个block 一定得调用,至于在哪里调用,倒是无所谓,我们也可以写在方法实现的第一行,或者最后一行。

示例工程地址:JS_OC_URL

iOS下JS与OC互相调用(二)--WKWebView 拦截URL的更多相关文章

  1. iOS下JS与OC互相调用(六)--WKWebView + WebViewJavascriptBridge

    上一篇文章介绍了UIWebView 如何通过WebViewJavascriptBridge 来实现JS 与OC 的互相调用,这一篇来介绍一下WKWebView 又是如何通过WebViewJavascr ...

  2. iOS下JS与OC互相调用(五)--UIWebView + WebViewJavascriptBridge

    WebViewJavascriptBridge是一个有点年代的JS与OC交互的库,使用该库的著名应用还挺多的,目前这个库有7000+star.我去翻看了它的第一版本已经是4年前了,在版本V4.1.4以 ...

  3. iOS下JS与OC互相调用(四)--JavaScriptCore

    前面讲完拦截URL的方式实现JS与OC互相调用,终于到JavaScriptCore了.它是从iOS7开始加入的,用 Objective-C 把 WebKit 的 JavaScript 引擎封装了一下, ...

  4. iOS下JS与OC互相调用(一)--UIWebView 拦截URL

    最近准备把之前用UIWebView实现的JS与原生相互调用功能,用WKWebView来替换.顺便搜索整理了一下JS 与OC 交互的方式,非常之多啊.目前我已知的JS 与 OC 交互的处理方式: * 1 ...

  5. iOS下JS与OC互相调用(三)--MessageHandler

    使用WKWebView的时候,如果想要实现JS调用OC方法,除了拦截URL之外,还有一种简单的方式.那就是利用WKWebView的新特性MessageHandler来实现JS调用原生方法. Messa ...

  6. iOS下JS与OC互相调用

    背景情况: app项目中有几个界面是需要经常变动的(不仅是内容还有UI布局等),比如活动宣传界面就是属于这一类.但是由于AppStore提交审核也是需要时间的,就算审核快,也不至于每次都为了这点事频繁 ...

  7. iOS下JS与OC互相调用(八)--Cordova详解+实战

    扯两句,可以跳过 由于项目中Cordova相关功能一直是同事在负责,所以也没有仔细的去探究Cordova到底是怎么使用的,又是如何实现JS 与 OC 的交互.所以我基本上是从零开始研究和学习Cordo ...

  8. iOS下JS与OC互相调用(八)--Cordova简单实战

    新建工程,添加Cordova 关键类 新建一个工程TestCordova 然后添加:confug.xml.Private 和 Public 两个文件夹里的所有文件 然后build 发现报错 为什么有会 ...

  9. iOS下JS与OC互相调用(七)--Cordova 基础

    Cordova 简介 在介绍Cordova之前,必须先提一下PhoneGap.PhoneGap 是Nitobi软件公司2008年推出的一个框架,旨在弥补web 和iOS 之间的不足,使得web 和 i ...

随机推荐

  1. hihocoder 1391 树状数组

    #1391 : Countries 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 There are two antagonistic countries, countr ...

  2. ●UVa 1589 Xiangqi(模拟)

    ●赘述题意 给出一个中国象棋残局,告诉各个棋子的位置,黑方只有1枚“将”,红方有至少2枚,至多7枚棋子,包含1枚“帅G”,和若干枚“车R”,“马H”,“炮C”.当前为黑方的回合,问黑方的“将”能否在移 ...

  3. hdu4542 && ZOJ2562(反素数)

    反素数: 对于任何正整数,其约数个数记为,例如,如果某个正整数满足:对任意的正整 数,都有,那么称为反素数. 有两个特点: 1.一个反素数的质因子必是从2开始的质数 2.如果,那么必有 最常见的问题如 ...

  4. [HNOI2009]最小圈

    题目描述 对于一张有向图,要你求图中最小圈的平均值最小是多少,即若一个圈经过k个节点,那么一个圈的平均值为圈上k条边权的和除以k,现要求其中的最小值 输入输出格式 输入格式: 第一行2个正整数,分别为 ...

  5. bzoj1069 [SCOI2007]最大土地面积 旋转卡壳

    1069: [SCOI2007]最大土地面积 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 3767  Solved: 1501[Submit][Sta ...

  6. C语言成语设计第一次作业

    一 1.求圆面积和周长 输入圆的半径,计算圆的周长和面积. 2.流程图 3.测试数据及运行结果 测试数据:r=7 运行结果 4.实验分析 问题:第一次输入提示时未加双引号 解决办法:发现问题后加了双引 ...

  7. glusterfs 4.0.1 event模块 分析笔记1

    1. 前言 在C语言i中,存储变量的结构体加上一组函数指针,大概就可以算是一个对象模型了:如果将一组函数指针捆绑为结构体, 后期根据配置或者环境需要绑定到不同实现模块中的一组函数,可以认为是C语言面对 ...

  8. 算法工程师:双非渣硕是如何获得百度、京东双SP

    本人本科硕士皆双非,和牛客大佬们没得比,目前拿到的还可以的offer就是百度SP和京东SP,都是做的推荐算法,其他的不说了. 先说一下个人经历吧,学校比较水,实验室没有项目,实习经历:腾讯实习+滴滴实 ...

  9. VMWare 学习目录

    Linux介绍 Linux入门--个人感想 Google怎么用linux 初入Linux Windows XP硬盘安装Ubuntu 12.04双系统图文详解 实例讲解虚拟机3种网络模式(桥接.nat. ...

  10. Linux的管理类命令及其使用方法

    文件操作相关有一些命令可以帮助我们"修剪"之前看到的文件树. $touch a.txt 如果a.txt不存在,生成一个新的空文档a.txt.如果a.txt存在,那么只更改该文档的时 ...