iOS下JS与OC互相调用(二)--WKWebView 拦截URL
在上篇文章中讲述了使用UIWebView拦截URL的方式来处理JS与OC交互。
由于UIWebView比较耗内存,性能上不太好,而苹果在iOS 8中推出了WKWebView。
同样的用WKWebView也可以拦截URL,做JS 与OC交互。关于WKWebView与UIWebView的对比,大家请自动百度或者google。
打开百度网页前 | 打开百度网页后 | |
---|---|---|
UIWebView | 内存47M | 内存75.6M,最高峰83M |
WKWebView | 内存47M | 内存51M |
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
{// 获取位置信息// 将结果返回给jsNSString *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 一定得调用,至于在哪里调用,倒是无所谓,我们也可以写在方法实现的第一行,或者最后一行。
相关文章:
基于模型的强化学习比无模型的强化学习更好?错!
作者 | Carles Gelada and Jacob Buckman编辑 | DeepRL来源 | 深度强化学习实验室(ID:Deep-RL)【导读】许多研究人员认为,基于模型的强化学习(MBRL)比无模型的强化学习(MFRL)具有更高的样本效率。但是&…

程序员的自我修养--链接、装载与库笔记:内存
1. 程序的内存布局 现代的应用程序都运行在一个内存空间里,在32位的系统里,这个内存空间拥有4GB(2的32次方)的寻址能力。应用程序可以直接使用32位的地址进行寻址,这被称为平坦(flat)的内存模型。在平坦的内存模型中,整个内存是一…

【Away3D代码解读】(四):主要模块简介
数据模块: Away3D中最核心的数据类是Mesh类,我们先看看Mesh类的继承关系: NamedAssetBase:为对象提供id和name属性,是Away3D大部分类的基类; Object3D:3D对象基类,提供方便操作3D对象…

程序员的自我修养--链接、装载与库笔记:运行库
1. 入口函数和程序初始化 程序从main开始吗?:操作系统装载程序之后,首先运行的代码并不是main的第一行,而是某些别的代码,这些代码负责准备好main函数执行所需要的环境,并且负责调用main函数,这…

iOS下JS与OC互相调用(三)--MessageHandler
使用WKWebView的时候,如果想要实现JS调用OC方法,除了拦截URL之外,还有一种简单的方式。那就是利用WKWebView的新特性MessageHandler来实现JS调用原生方法。 MessageHandler 是什么? WKWebView 初始化时,有一个参数叫…
北大教授张大庆:无线感知,让你变老也优雅
受访者 | 张大庆记者 | 胡巍巍出品 | CSDN(ID:CSDNnews)在国内高校中,北大的校庆日很特殊——5月4日。这一天,也是青年节。北大,是五四运动的策源地。100年来,“爱国、进步、民主、科学”的五四…

总结 20 个开发细节
2019独角兽企业重金招聘Python工程师标准>>> 1:提交到SVN的代码必须有提交备注,以便于以后查看。 2:如考虑页面缓存,可以在路径后增加随机数:url "&TimeS" Math.random();。 3:…

程序员的自我修养--链接、装载与库笔记:系统调用与API
系统调用(System Call)是应用程序(运行库也是应用程序的一部分)与操作系统内核之间的接口,它决定了应用程序是如何与内核打交道的。无论程序是直接进行系统调用,还是通过运行库,最终还是会到达系统调用这个层面上。 1. 系统调用介绍 什么是…

iOS下JS与OC互相调用(四)--JavaScriptCore
前面讲完拦截URL的方式实现JS与OC互相调用,终于到JavaScriptCore了。它是从iOS7开始加入的,用 Objective-C 把 WebKit 的 JavaScript 引擎封装了一下,提供了简单快捷的方式与JavaScript交互。 关于JavaScriptCore的使用有两篇很好的文章&…
围巾都这么黑科技了,是我见识少了
有一个永恒的话题:北方冷一点还是南方冷一点?答案是:哪里都冷!冬天最痛苦的莫过于走出空调房——刺骨的风直直的从领口处灌进去那叫一个“透心凉,心飞扬”缠了好几圈的大围巾却根本没什么保暖效果每当这时候࿰…

【教程】【FLEX】#004 反射机制
总结: 目前用到反射的主要有两个方法 1. getDefinitionByName //根据类名,返回对象(反射实例化对象) 2. describeType //根据对象,返回XML格式的属性,方法等信息(反射得到…

iOS下JS与OC互相调用(五)--UIWebView + WebViewJavascriptBridge
WebViewJavascriptBridge是一个有点年代的JS与OC交互的库,使用该库的著名应用还挺多的,目前这个库有7000star。我去翻看了它的第一版本已经是4年前了,在版本V4.1.4以及之前,该库只有一个类和一个js 的txt文件,所以旧版…

OpenCV代码提取:Windows上通过DShow获取Camera视频
在OpenCV 3.1中获取视频的模块在videoio(video input and output module)中,调用VideoCapture类接口,除了videoio模块外还依赖core、highgui、imgproc、imgcodecs四个模块,而OpenCV 2.4.13.6仅需要core、highgui、imgproc三个模块。3.1中的vi…
迁移学习与图神经网络“合力”模型:用DoT-GNN克服组重识别难题
作者 | Ziling Huang、Zheng Wang、Wei Hu、Chia-Wen Lin、Shin’ichi Satoh译者 | 刘畅编辑 | Jane出品 | AI科技大本营(ID:rgznai100)【导读】目前,大多数行人重识别(ReID)方法主要是从收集的单个人图像数…

struts2 select 默认选中
jsp:<s:select list"#{1:男,2:女}" name"sex"/> action:private String sex;sex属性有get/set方法。在业务方法中设置sex "2";select会默认选中。

通过Windows DShow获取设备名、支持的编解码及视频size列表实现
之前在https://blog.csdn.net/fengbingchun/article/details/102641967中介绍过通过DShow获取Camera视频的实现,即调用VideoCapture类。在OpenCV的VideoCapture类中并没有提供获取Camera设备列表、支持的编解码类型列表及支持的video size列表接口,这里基…
15篇论文全面概览BERT压缩方法
作者 | Mitchell A. Gordon译者 | 孙薇出品 | AI科技大本营(ID:rgznai100)模型压缩可减少受训神经网络的冗余——由于几乎没有BERT或者BERT-Large模型可用于GPU及智能手机上,这一点就非常有用了。另外,内存与推理速度的提高也能节…

iOS下JS与OC互相调用(七)--Cordova 基础
Cordova 简介 在介绍Cordova之前,必须先提一下PhoneGap。PhoneGap 是Nitobi软件公司2008年推出的一个框架,旨在弥补web 和iOS 之间的不足,使得web 和 iPhone SDK 之间的交互更容易。后来又加入了Android SDK 和BlackBerry SDK,再然…

在linux上MySQL的三种安装方式
安装MySQL的方式常见的有三种:方式一:rpm安装(1) 操作系统发行商提供的(2) MySQL官方提供的(版本更新,修复了更多常见BUG)www.mysql.com/downloads关于MySQL中rpm包类型的介绍:MySQL-client 客户端…

通过libjpeg-turbo实现对jpeg图像的解码
之前在https://blog.csdn.net/fengbingchun/article/details/89715416中介绍过通过libjpeg-turbo接口实现将数据编码或压缩成jpeg数据并通过FILE的fwrite接口将其直接保存成*.jpg图像,当时用的是libjpeg的接口,其实还可以使用turbojpeg api的接口即tjCom…
AI+大数据顶级技术盛会开幕在即,6.6折特惠票限时抢购
2019年12月5-7日,由中国计算机学会主办,CCF 大数据专家委员会承办,CSDN、中科天玑数据科技股份有限公司协办的中国大数据技术大会(BDTC 2019)将于北京长城饭店隆重举行。届时,超过百位顶尖技术专家将齐聚于…

iOS下JS与OC互相调用(八)--Cordova详解+实战
1.新建工程,添加Cordova 关键类 我这里用Xcode 8 新建了一个工程,叫 JS_OC_Cordova,然后将Cordova关键类添加进工程。 有哪些关键类呢? 这里添加config.xml 、Private 和 Public 两个文件夹里的所有文件。工程目录结构如下: 然后…

iOS多线程编程之NSOperation和NSOperationQueue的使用
使用 NSOperation的方式有两种, 一种是用定义好的两个子类: NSInvocationOperation 和 NSBlockOperation。 另一种是继承NSOperation 如果你也熟悉Java,NSOperation就和java.lang.Runnable接口很相似。和Java的Runnable一样,NSOpe…

Swift - 使用SwiftHTTP通过HTTPS进行网络请求,及证书的使用
(本文代码已升级至Swift3)一,证书的生成,以及服务器配置参考我前面写的这篇文章:Tomcat服务器配置https双向认证(使用keytool生成证书)文章详细介绍了HTTPS,SSL/TLS。还有使用key to…

Linux下通过v4l2获取视频设备名、支持的编解码及视频size列表实现
早些时候给出了在Windows下通过dshow获取视频设备信息的实现,包括获取视频设备名、获取每种视频设备支持的编解码格式列表、每种编解码格式支持的video size列表,见:https://blog.csdn.net/fengbingchun/article/details/102806822 下面给出…
12种主流编程语言输出“ Hello World ”,把我给难住了!
作为一名程序员,在初步学习编程想必都绕不开一个最为基础的入门级示例“Hello World”,那么,你真的了解各个语言“Hello World”的正确写法吗?在我们刚开始打开编程世界的时候,往往写的第一个程序都是简单的文本输出&a…

军哥lnmp一键安装包nginx支持pathinfo配置
ssh里执行:cat > /usr/local/nginx/conf/pathinfo.conf << EOF set $real_script_name $fastcgi_script_name; if ($fastcgi_script_name ~ "(.?\.php)(/.*)") { set $real_script_name $1; set $path_info $2; } fastcgi_param SCRIPT_FILENAM…

Effective STL 50条有效使用STL的经验笔记
Scott Meyers大师Effective三部曲:Effective C、More Effective C、Effective STL,这三本书出版已很多年,后来又出版了Effective Modern C。 Effective C的笔记见:https://blog.csdn.net/fengbingchun/article/details/102761542…

HTTPS网络加密双向验证-使用AFNetworking封装
1.首先使用OC封装请求头 #import <Foundation/Foundation.h> #import "AFNetworking.h" interface HttpsHandler : NSObject (AFHTTPSessionManager *)setHttpsMange; end 2.实现方法 (AFHTTPSessionManager *)setHttpsMange; { NSString *certFilePath […
30分钟搞定数据竞赛刷分夺冠神器LightGBM!
作者 | 梁云1991来源 | Python与算法之美(ID:Python_Ai_Road)【导读】LightGBM可以看成是XGBoost的升级加强版本,2017年经微软推出后,便成为各种数据竞赛中刷分夺冠的神兵利器。一,LightGBM和XGBoost对比正如其名字中的Light所蕴含…