WKWebView讲解与使用
随着IOS开发的应用,对于网页嵌入也越来越多了,在IOS 8之前我们使用UIWebView展示详情页,自从IOS 8之后就出现了WKWebView,相比UIWebView,WKWebView优化了较多的体验。下面将讲述WKWebView的知识点以及运用,大概需要花费10-20分钟时间,希望对大家有所帮助!!!
一、WKWebView优点
WKWebView采用跨进程方案,Nitro JS解析器,高达60fps的刷新率,理论上性能和Safari比肩,而且对H5也实现了高度支持。
1.WKWebView的内存开销比UIWebView小很多
2.内置手势
3.支持了更多的HTML5特性
4.有Safari相同的JavaScript引擎
5.提供常用的属性,如加载网页进度的estimatedProgress属性
下面来对比UIWebView和WKWebView的流程区别(左边是UIWebView,右边是WKWebView)

WKWebView的流程粒度更加细致,不但在不但在请求的时候会询问WKWebView是否请求数据,还会在返回数据之后询问WKWebView是否加载数据。
#请求数据的时候询问
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
#返回数据的时候询问
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;
在流程中,WKWebView返回的错误粒度也比UIWebView细:
#请求数据时发生的error
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error;
#请求之后加载H5发生的error
- (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error;
二、WKWebView基本使用
2.1 基本使用
2.1.1 使用WKWebView引用头文件
- (void)setupWebview{
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.selectionGranularity = WKSelectionGranularityDynamic;
config.allowsInlineMediaPlayback = YES;
WKPreferences *preferences = [WKPreferences new];
//是否支持JavaScript
preferences.javaScriptEnabled = YES;
//不通过用户交互,是否可以打开窗口
preferences.javaScriptCanOpenWindowsAutomatically = YES;
config.preferences = preferences;
WKWebView *webview = [[WKWebView alloc] initWithFrame:CGRectMake(, , KScreenWidth, KScreenHeight - ) configuration:config];
[self.view addSubview:webview];
/* 加载服务器url的方法*/
NSString *url = @"https://www.baidu.com";
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
[webview loadRequest:request];
webview.navigationDelegate = self;
webview.UIDelegate = self;
}
WKWebViewConfiguration和WKPreferences中很多属性对WebView初始化进行设置。
2.1.2 下面遵循协议和实现的协议方法:
#pragma mark - WKNavigationDelegate
/* 页面开始加载 */
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
}
/* 开始返回内容 */
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{ }
/* 页面加载完成 */
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{ }
/* 页面加载失败 */
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation{ }
/* 在发送请求之前,决定是否跳转 */
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
//允许跳转
decisionHandler(WKNavigationActionPolicyAllow);
//不允许跳转
//decisionHandler(WKNavigationActionPolicyCancel);
}
/* 在收到响应后,决定是否跳转 */
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{ NSLog(@"%@",navigationResponse.response.URL.absoluteString);
//允许跳转
decisionHandler(WKNavigationResponsePolicyAllow);
//不允许跳转
//decisionHandler(WKNavigationResponsePolicyCancel);
}
三、WKWebView开发细节
3.1 url 中文处理
有时候我们加载的url中出现了中文,需要我们手动转码,但是同时又要保证URL中的特殊字符保持不变,那么我们可以使用下面的方法(方法)
- (NSURL *)url{
#pragma clang diagnostic push
#pragma clang diagnostic ignored"-Wdeprecated-declarations"
return [NSURL URLWithString:(NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, (CFStringRef)@"!$&'()*+,-./:;=?@_~%#[]", NULL,kCFStringEncodingUTF8))];
#pragma clang diagnostic pop
}
3.2 获取h5中的标题以及添加进度条
获取h5中的标题和添加进度条放在一起展示看起来更明朗一点,在初始化webView,添加两个观察者分别用来监听webView的estimateProgress和title属性
webview.navigationDelegate = self;
webview.UIDelegate = self; [webview addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
[webview addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:NULL];
添加创建进度条,并添加进度条图层属性:
@property (nonatomic,weak) CALayer *progressLayer;
-(void)setupProgress{
UIView *progress = [[UIView alloc]init];
progress.frame = CGRectMake(, , KScreenWidth, );
progress.backgroundColor = [UIColor clearColor];
[self.view addSubview:progress];
CALayer *layer = [CALayer layer];
layer.frame = CGRectMake(, , , );
layer.backgroundColor = [UIColor greenColor].CGColor;
[progress.layer addSublayer:layer];
self.progressLayer = layer;
}
实现观察者的回调方法:
#pragma mark - KVO回馈
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<nskeyvaluechangekey,id> *)change context:(void *)context{
if ([keyPath isEqualToString:@"estimatedProgress"]) {
self.progressLayer.opacity = ;
if ([change[@"new"] floatValue] <[change[@"old"] floatValue]) {
return;
}
self.progressLayer.frame = CGRectMake(, , KScreenWidth*[change[@"new"] floatValue], );
if ([change[@"new"]floatValue] == 1.0) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(. * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.progressLayer.opacity = ;
self.progressLayer.frame = CGRectMake(, , , );
});
}
}else if ([keyPath isEqualToString:@"title"]){
self.title = change[@"new"];
}
}</nskeyvaluechangekey,id>
3.3 添加userAgent信息
有时候h5的欧版需要我们为WebView的请求添加userAgent,用来识别操作系统等一下信息,但是如果每次用到webView都要添加一次的话会比较麻烦,下面是一种解决问题的办法
在Appdelegate中添加一个WKWebView的属性,启动app时直接为该属性添加userAgent:
- (void)setUserAgent {
_webView = [[WKWebView alloc] initWithFrame:CGRectZero];
[_webView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id result, NSError *error) {
if (error) { return; }
NSString *userAgent = result;
if (![userAgent containsString:@"/mobile-iOS"]) {
userAgent = [userAgent stringByAppendingString:@"/mobile-iOS"];
NSDictionary *dict = @{@"UserAgent": userAgent};
[TKUserDefaults registerDefaults:dict];
}
}];
}
这样一来,在app创建webView时存在了我们添加的userAgent的信息。
3.4 JS调用OC
js会通过以下方法调用原生方法
window.webkit.messageHandlers.<#对象名#>.postMessage(<#参数#>)
在原生中我们只要实现WKScriptMessageHandler的代理方法就可以了,值得注意的是参数name需要与上述代码中对象名一致。
// 添加scriptMessageHandler
- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;
最后在
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
在这个方法中获取做下判断,响应对应的方法即可:
// 初始化WKWebView,在实例化WKWebViewConfiguration对象的时候我们同时添加scriptMessageHandler
//进行配置控制器
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
//实例化对象
configuration.userContentController = [WKUserContentController new];
//调用JS方法
[configuration.userContentController addScriptMessageHandler:self name:@"btnClick"]; #pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if ([message.name isEqualToString:@"btnClick"]) {
NSDictionary *jsData = message.body;
NSLog(@"%@", message.name, jsData);
//读取js function的字符串
NSString *jsFunctionString = jsData[@"result"];
//拼接调用该方法的js字符串(convertDictionaryToJson:方法将NSDictionary转成JSON格式的字符串)
NSString *jsonString = [NSDictionary convertDictionaryToJson:@{@"test":@"", @"data":@""}];
NSString *jsCallBack = [NSString stringWithFormat:@"(%@)(%@);", jsFunctionString, jsonString];
//执行回调
[self.weWebView evaluateJavaScript:jsCallBack completionHandler:^(id _Nullable result, NSError * _Nullable error) {
if (error) {
NSLog(@"err is %@", error.domain);
}
}];
}
}
以上需要注意的是,由于message的body只能是NSNumber,NSString,NSDate,NSArray,NSDictionary,NSNull这几种类型,我们无法将js函数直接原生,在需要进行回调的环境下,我们将js回调函数转为String后再传给原生,再由原生获取后进行回调操作,实际上这是已经进行了动态js注入。

3.5 OC调用JS
动态注入js方法就比较简单了,我们只要实现相应的方法就可以。
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;
下面有一段示例代码
// 此处是设置需要调用的js方法以及将对应的参数传入,需要以字符串的形式
NSString *jsFounction = [NSString stringWithFormat:@"getAppConfig('%@')", APP_CHANNEL_ID];
// 调用API方法
[self.weexWebView evaluateJavaScript:jsFounction completionHandler:^(id object, NSError * _Nullable error) {
NSLog(@"obj:%@---error:%@", object, error);
}];
以上就是WKWebView的基本使用,希望大家对WKWebView的理解有所提高,谢谢!!!
WKWebView讲解与使用的更多相关文章
- WKWebView使用及注意点
iOS8之后,苹果推出了WebKit这个框架,用来替换原有的UIWebView,新的控件优点多多,不一一叙述.由于一直在适配iOS7,就没有去替换,现在仍掉了iOS7,以为很简单的就替换过来了,然而在 ...
- WKWebView与Js实战(OC版)
前言 上一篇专门讲解了WKWebView相关的所有类.代理的所有API.那么本篇讲些什么呢?当然是实战了! 本篇文章教大家如何使用WKWebView去实现常用的一些API操作.当然,也会有如何与JS交 ...
- iOS下JS与OC互相调用(二)--WKWebView 拦截URL
在上篇文章中讲述了使用UIWebView拦截URL的方式来处理JS与OC交互. 由于UIWebView比较耗内存,性能上不太好,而苹果在iOS 8中推出了WKWebView. 同样的用WKWebVie ...
- 关于用wkwebview加载沙盒documents下html文件 模拟器可以,真机不行的解决方案
最近也遇到这个问题,把我解决的思路记录一下 1.问题: 用wkwebview加载(loadRequest)沙盒documents下html文件 模拟器可以,真机不行 (前提是html内部含引用外联样式 ...
- WKWebView 使用及注意事项
iOS8之后,苹果推出了WebKit这个框架,用来替换原有的UIWebView,新的控件优点多多.由于一直在适配iOS7,就没有去替换,现在仍掉了iOS7,以为很简单的就替换过来了,然而在替换的过程中 ...
- 聊聊WKWebView
聊一聊WKWebView 前言 由于之前一直在用UIWebView,所以对于WKWebView只是停留在知道,了解的状态,并未深入的去研究.前天一个项目要求支持iOS8以上,要加入一个web界面.在习 ...
- WKWebView的新特性与使用
在WWDC2014中,苹果推出了最新的iOS8系统,其中也伴随着很多控件的更新与升级.其中全新的WebKit库让人很是兴奋.本文也将讲解到WebKit中更新的WKWebView控件的新特性与使用方法, ...
- 网易严选的wkwebview测试之路
本文来自网易云社区 作者:孙娇 UIWebView是苹果继承于UIView封装的一个加载web内容的类,它可以加载任何远端的web数据展示在你的页面上,你可以像浏览器一样前进后退刷新等操作.不过苹果在 ...
- iOS适配UIViewView/WKWebView,H5生成长图,仿微信进度条
前段时间撸代码猥琐发育的时候,设计师老王给了张截图某宝APP上一个生成长图分享的功能,正好公司有这个需求,于是在立马开始操练起来!在万能的度娘上搜集整理资料后发现很多文章介绍的方案对WKWebView ...
随机推荐
- poj 3687
Description Windy has N balls of distinct weights from 1 unit to N units. Now he tries to label them ...
- (5)STM32使用HAL库实现串口通讯——实战操作
功能需求: (1)对接收的字符串原样返回(每10个字符一次). (2)发送一个字符串完成后改变LED的状态. 1.创建工程 使用的是F407Discovery,4个LED对应PD12-PD14. (1 ...
- (2)STM32使用HAL库操作外部中断——理论讲解
1.中断触发过程 对主程序压栈--把中断服务函数的地址写入到程序计数器(PC)--执行中断服务函数 2.中断向量表 中断服务函数的地址在STM32的手册上的中断向量表中(如下是一部分): 如上表所示, ...
- HTML5网页录音和上传到服务器,支持PC、Android,支持IOS微信
准备做一个网页版聊天界面,表情啊.图片啊.上传文件啊都应该要有,视频就算了,语音还是要的. 本文记录的是在网页上用GitHub上的Recorder进行在线录音和上传到服务器,前几天升了一下级,以后有时 ...
- MySQL安装及环境搭建
一.Windows 上安装 MySQL Windows 上安装 MySQL 相对简单,最新版本下载地址: 官网:https://dev.mysql.com/downloads/mysql/ 下载步骤: ...
- sau交流学习社区--songEagle开发系列:Vue.js + Koa.js项目中使用JWT认证
一.前言 JWT(JSON Web Token),是为了在网络环境间传递声明而执行的一种基于JSON的开放标准(RFC 7519). JWT不是一个新鲜的东西,网上相关的介绍已经非常多了.不是很了解的 ...
- java游戏开发杂谈 - 线程
线程,让游戏拥有了动态变化的能力. java的图形界面,在启动的时候,就开始了一个线程. 这个线程负责处理:JFrame.JPanel等的绘制.事件处理. 它是由操作系统调用的,在程序启动时开启,程序 ...
- SpringBoot进阶教程(二十七)整合Redis之分布式锁
在之前的一篇文章(<Java分布式锁,搞懂分布式锁实现看这篇文章就对了>),已经介绍过几种java分布式锁,今天来个Redis分布式锁的demo.redis 现在已经成为系统缓存的必备组件 ...
- 服务端预渲染之Nuxt(爬坑篇)
Nuxt是解决SEO的比较常用的解决方案,随着Nuxt也有很多坑,每当突破一个小技术点的时候,都有很大的成就感,在这段时间里着实让我痛并快乐着.在这里根据个人学习情况,所踩过的坑做了一个汇总和总结. ...
- .net double类型转string类型的坑
之前项目当中的接入的高德逆地理编码功能偶尔会出现参数错误的bug,经过排查服务端异常log,发现请求的url中的location参数中的小数点变成了逗号. 代码如下 public async Task ...