聊一聊WKWebView

前言

由于之前一直在用UIWebView,所以对于WKWebView只是停留在知道,了解的状态,并未深入的去研究。前天一个项目要求支持iOS8以上,要加入一个web界面。在习惯性使用UIWebView写到一半的时候,突然想使用WKWebView去实现,所以专门花费了些时间去研究了一下WKWebView,很是喜欢。

正文

接下来纪录一下使用WKWebView的过程细节。但关于WKWebView与js互交的部分保留意见,因为并没有深入去研究这一点。

1、引入WebKit库

Apple方面为使用WKWebView专门添加了WebKit库,在使用WKWebView时候必须引入WebKit库才可以。

#import <WebKit/WebKit.h> 

2、初始化WKWebView

在文档中可以看出,WKWebView的初始化方法有两种:

- (instancetype)initWithFrame:(CGRect)frame;
- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration NS_DESIGNATED_INITIALIZER

- 我们大多使用第一种方式,这也是文档中默认的一种方式。这里不再多说。
- 关于第二种方式,其实就是在初始化WKWebView时,给webView做一个配置,我这里给出一段简单的配置代码:

WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc]init];
config.preferences = [WKPreferences new];
config.preferences.minimumFontSize = .f;
config.preferences.javaScriptEnabled = YES; //The default value is YES
config.preferences.javaScriptCanOpenWindowsAutomatically = NO;//The default value is NO in iOS and YES in OS X.
//config.preferences.javaEnabled = NO ; //The default value is NO .不在iphone中使用的方法
config.userContentController = [WKUserContentController new];
self.webView = [[WKWebView alloc]initWithFrame:self.view.bounds configuration:config];

注:其实第一种方式,虽然我们并没有指定初始化的配置,但Apple也为我们指定了一个默认的配置。

3、加载网页

方法有几种,我们常用的是

NSURLRequest *request = [[NSURLRequest alloc]initWithURL:[NSURL URLWithString:@"https://www.baidu.com"]];
[self.webView loadRequest:request];

剩下的几种为:

[self.webView loadHTMLString:(nonnull NSString *) baseURL:(nullable NSURL *)];

[self.webView loadFileURL:(nonnull NSURL *) allowingReadAccessToURL:(nonnull NSURL *)];

[self.webView loadData:(nonnull NSData *) MIMEType:(nonnull NSString *) characterEncodingName:(nonnull NSString *) baseURL:(nonnull NSURL *)];

4、加载js代码

// 图片缩放的js代码
NSString *js = @"var count = document.images.length;for (var i = 0; i < count; i++) {var image = document.images[i];image.style.width=500;image.style.height=600;};window.alert('找到' + count + '张图');";
// 根据JS字符串初始化WKUserScript对象
WKUserScript *script = [[WKUserScript alloc] initWithSource:js injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
// 根据生成的WKUserScript对象,初始化WKWebViewConfiguration
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
[config.userContentController addUserScript:script];
_webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
[_webView loadHTMLString:@"<head></head>![](//upload-images.jianshu.io/upload_images/2269924-034fead1cdf2bfe0.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)"baseURL:nil];
[self.view addSubview:_webView];

5、代理

WKWebView的代理有两个:WKNavigationDelegate 和 WKUIDelegate

5.1、 WKNavigationDelegate(加载界面时调用的协议方法)

过程:

1. 在请求发送之前,决定是否跳转
2. 页面开始加载时调用
3. 在收到响应后,决定是否跳转
4. 内容开始加载时调用
5. 接收到服务器跳转请求之后调用(不一定调用该方法)
6. 页面加载完成时调用
7. 请求失败时调用

协议方法如下:

//页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation
{
NSLog(@"页面开始加载时调用。 2");
}
//内容返回时调用,得到请求内容时调用(内容开始加载) -> view的过渡动画可在此方法中加载
- (void)webView:(WKWebView *)webView didCommitNavigation:( WKNavigation *)navigation
{
NSLog(@"内容返回时调用,得到请求内容时调用。 4");
}
//页面加载完成时调用
- (void)webView:(WKWebView *)webView didFinishNavigation:( WKNavigation *)navigation
{
NSLog(@"页面加载完成时调用。 5");
}
//请求失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error
{
NSLog(@"error1:%@",error);
}
-(void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error
{
NSLog(@"error2:%@",error);
}
//在请求发送之前,决定是否跳转 -> 该方法如果不实现,系统默认跳转。如果实现该方法,则需要设置允许跳转,不设置则报错。
//该方法执行在加载界面之前
//Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Completion handler passed to -[ViewController webView:decidePolicyForNavigationAction:decisionHandler:] was not called'
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
//允许跳转
decisionHandler(WKNavigationActionPolicyAllow); //不允许跳转
// decisionHandler(WKNavigationActionPolicyCancel);
NSLog(@"在请求发送之前,决定是否跳转。 1");
}
//在收到响应后,决定是否跳转(同上)
//该方法执行在内容返回之前
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
{
//允许跳转
decisionHandler(WKNavigationResponsePolicyAllow);
//不允许跳转
// decisionHandler(WKNavigationResponsePolicyCancel);
NSLog(@"在收到响应后,决定是否跳转。 3"); }
//接收到服务器跳转请求之后调用
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation
{
NSLog(@"接收到服务器跳转请求之后调用");
}
-(void)webViewWebContentProcessDidTerminate:(WKWebView *)webView
{
NSLog(@"webViewWebContentProcessDidTerminate");
}

5.2、WKUIDelegate

这方面包括:创建新的WebView、界面弹出提示框

创建新的WebView

// 创建一个新的WebView
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;

界面弹出提示框

系统提供了三种弹出提示框的方法:警告框、确认框、输入框

直接查看代码如下:

//警告框
/**
webView界面中有弹出警告框时调用
@param webView web视图调用委托方法
@param message 警告框提示内容
@param frame 主窗口
@param completionHandler 警告框消失调用
*/
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
completionHandler();
NSLog(@"警告框");
}
//输入框
/**
web界面中弹出输入框时调用
@param webView web视图调用委托方法
@param prompt 输入消息的显示
@param defaultText 初始化时显示的输入文本
@param frame 主窗口
@param completionHandler 输入结束后调用
*/
-(void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler
{
NSLog(@"输入框");
completionHandler(@"http");
}
//确认框
/**
显示一个JavaScript确认面板
@param webView web视图调用委托方法
@param message 显示的信息
@param frame 主窗口
@param completionHandler 确认后完成处理程序调用
*/
-(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler
{
NSLog(@"确认框");
completionHandler(YES);
}

以上就是WKWebView基本使用方法,其他的不做扩展和补充。也许以后再深入研究时,会有不一样的看法,到时再做推翻或补充。

以下是个人的一点看法:

1. WKWebView是在iOS8之后出现的新的网页加载控件,将来也必将取代UIWebView,这是毋庸置疑的事情。
2. 关于项目优化方面:其实很多人建议在项目中添加WKWebView去替代UIWebView。以未来的发展趋势来看,这点无可厚非。

我下面想说的是站在老项目并且其中内嵌网页比较多的立场的,iOS8以上使用WKWebView,iOS8以下使用UIWebView。这是目前解决方案的好办法。但维护和优化都需要成本,时间也是成本的一部分。

这里给出几个讲解<code>WKWebView</code>的

聊聊WKWebView的更多相关文章

  1. WKWebView针对于Cordova的IOS平台性能提升

    使用cordova做跨平台开发已久,针对于Android的性能与页面渲染问题仍然让人头疼,因为仍然有一部分人使用性能一般的手机,版本在 4.2-4.4之间,甚至都无法支持HTML5的flex布局,使得 ...

  2. 聊聊Unity项目管理的那些事:Git-flow和Unity

    0x00 前言 目前所在的团队实行敏捷开发已经有了一段时间了.敏捷开发中重要的一个话题便是如何对项目进行恰当的版本管理.项目从最初使用svn到之后的Git One Track策略再到现在的GitFlo ...

  3. Mono为何能跨平台?聊聊CIL(MSIL)

    前言: 其实小匹夫在U3D的开发中一直对U3D的跨平台能力很好奇.到底是什么原理使得U3D可以跨平台呢?后来发现了Mono的作用,并进一步了解到了CIL的存在.所以,作为一个对Unity3D跨平台能力 ...

  4. fir.im Weekly - 聊聊 Google 开发者大会

    中国互联网的三大错觉:索尼倒闭,诺基亚崛起,谷歌重返中国.12月8日,2016 Google 开发者大会正式发布了Google Developers 中国网站 ,包含了Android Develope ...

  5. 聊聊asp.net中Web Api的使用

    扯淡 随着app应用的崛起,后端服务开发的也越来越多,除了很多优秀的nodejs框架之外,微软当然也会在这个方面提供更便捷的开发方式.这是微软一贯的作风,如果从开发的便捷性来说的话微软是当之无愧的老大 ...

  6. 没有神话,聊聊decimal的“障眼法”

    0x00 前言 在上一篇文章<妥协与取舍,解构C#中的小数运算>的留言区域有很多朋友都不约而同的说道了C#中的decimal类型.事实上之前的那篇文章的立意主要在于聊聊使用二进制的计算机是 ...

  7. WKWebView浅析

    原文链接:supermokey WKWebView 一个WKWebView对象展示交互的web内容,例如应用于app内的浏览器.你可以在你的App中使用WKWebView. 综述 Important: ...

  8. iOS网络3—UIWebView与WKWebView使用详解

    一.整体介绍 UIWebView自iOS2就有,WKWebView从iOS8才有,毫无疑问WKWebView将逐步取代笨重的UIWebView.通过简单的测试即可发现UIWebView占用过多内存,且 ...

  9. 聊聊 C 语言中的 sizeof 运算

    聊聊 sizeof 运算 在这两次的课上,同学们已经学到了数组了.下面几节课,应该就会学习到指针.这个速度的确是很快的. 对于同学们来说,暂时应该也有些概念理解起来可能会比较的吃力. 先说一个概念叫内 ...

随机推荐

  1. 【BZOJ4445】[Scoi2015]小凸想跑步 半平面交

    [BZOJ4445][Scoi2015]小凸想跑步 Description 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸n边形,N个顶点按照逆时针从0-n-l编号.现 ...

  2. Apache服务器301重定向去掉.html和.php

    在做优化网站的时候,会考虑到网站整站的集权: 考虑到网站可以生成静态,首先,让网站优先访问 index.html 之后考虑:去掉 .html 和 .php. 利用 .htaccess <IfMo ...

  3. python 读取一个目录下的所有目录和文件

    #!/usr/bin/python # -*- coding:utf8 -*- import os allFileNum = 0 def printPath(level, path): global ...

  4. HTTP与HTTPS对访问速度(性能)的影响【转】

    1 前言 HTTPS 在保护用户隐私,防止流量劫持方面发挥着非常关键的作用,但与此同时,HTTPS 也会降低用户访问速度,增加网站服务器的计算资源消耗. 本文主要介绍 https 对用户体验的影响. ...

  5. ELKStack之消息队列

    redis消息队列 安装redis yum -y install redis 修改配置文件 修改ip 后台运行 启动 systemctl start redis 查看 lsof -i:6379 连接 ...

  6. Fata7y Ya Warda! SPOJ - DRUIDEOI 单调栈

    题意:1e5个数围成一个环.现在要输出每个数左右第一个大于它的数的下标.若没有,则输出-1. 题解:单调栈板题.只是要把数据压入栈压两遍来模仿环.    具体分析:考虑一个递减的数列.要找左边最大的 ...

  7. 用栈来递归 模板 honoi

    用栈来模拟递归的技巧 #define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<vector> #include& ...

  8. laravel5.1接收ajax数据

    前台: $.ajax({ type: 'POST', url: '{!! url('aw/data') !!}', data:{'_token':'<?php echo csrf_token() ...

  9. SecureFX 中文乱码

      1. 找到SecureFX配置文件夹(选项–全局选项,常规下的配置文件夹),比如:C:\Users\James\AppData\Roaming\VanDyke\Config\Sessions 2. ...

  10. 伪列ROWNUM、ROWID部分用法

    ROWNUM是逻辑值,不可以参与计算 ROWID是物理值,可以参与计算 在ROWNUM和ROWID使用中,现将查找结果形成一个结果集 在结果集中给ROWID 和ROWNUM别名,在外层中使用这个别名找 ...