43- WKWebView项目实践分享(二)- WKWebView介绍

系列文章:

前言

本文中,我们先介绍一下WKWebView,对比UIWebView它的优缺点。然后再看下WKWebView的主要API和其中的属性,基本使用。

WkWebView的优点和注意点

在2014年的WWDC上,苹果针对WKWebView有专门的讲解。下边,通过WWDC的课件上来看一下WKWebView的特点:

WKWebView所属WebKit特点1
WKWebView所属WebKit特点2
WKWebView所属WebKit特点3-多进程结构

WKWebView的多进程结构

上图中提到,WKWebView的Multi-process Architecture多进程结构具有【更完整的执行流程控制】和【低能耗】的两个特点。下边,针对这两个特点详细解释一下:

一般而言,一个程序开启之后就会占用一个进程,但是这不是唯一的。也存在一个程序对应多个进程(比如说程序的"多开"),或者一个进程对应多个程序的情况(比如说一个系统级别的工具DirectX,你同时打开多个游戏都会使用到它)。 对于WKWebView,你每创建一个webView出来,默认的都会对应一个叫做Web Content Process的进程。当然,你也可以不多对对,可以多对一。这样就可以使创建出的多个webView对应同一个的Web Content Process的进程。这个特点也涉及到了一个共享缓存数据的问题,后边文章会详细提到。

QQ20190929-154127@2x.png

基于这个特点,我们打开一个应用程序A,然后又在应用A中打开一个webView,这个时候其实是两个进程,没错, WKWebView在APP进程之外单独开了一个进程, 这一点非常重要。如下图:

来自:《教你使用 WKWebView 的正确姿势》

因为WKWebView开辟的是独立于App之外的进程,webView占用的内存是转移到了自己的进程中,而不是在App的进程中。所以我们在查看内存占用情况的时候会看到,加载同一个网页的时候(复杂绘制的大型网页更明显),使用WKWebView的App会比使用UIWebView的App占用内存小。 也许有同学会想到,这有什么用呢,WKWebView不仍然还是在占用内存。我们举一个例子来说明这么设计的好处。当开启一个webView十分耗费内存并且超过了苹果的安全值时,使用UIWebView的App会被系统直接杀掉。而使用WKWebView的App,被杀掉的只是WKWebView,体现在APP上的就是webView白屏了。此时,我们依然可以退出webView所在的界面,继续愉快的玩耍App的其他功能。

占用内存低

另外,关于占用内存低这个特点。我们监测内存的时候会发现,除了刚开始打开webView的时候,WKWebView会比UIWebView占用内存低之外。在后续的用户操作中,WKWebView仍然会很好的内存控制,而用了UIWebView的APP占用的内存会呈现出上涨。我觉得,这也还是因为WKWebView多进程架构的功劳。如下图:

UIWebView使用过程中,App的内存会有上涨的问题
WKWebView的使用过程中,App的内存稳定

WkWebView的注意点

在实际业务的接入和线上使用过程中,WKWebView有些地方并不方便,比如Cookie和黑魔法NSURLProtocol

  • Cookie: 在WKWebView中,并不能像UIWebView那样很方便的设置Cookie,虽然可以通过其它方式实现,但是总体给人的感觉是Cookie并不在最开始苹果设计WKWebView的规划之内。之所以这样,猜想是苹果团队在设计WKWebView的时候,就没想过要让客户端干预Cookie,而是Cookie由HTML5后台完全控制,这么做是为了保证敏感数据安全。所以在iOS11以下的版本API中,并没有类似UIWebView中NSHTTPCookieStorage这样的可以直接设置和存储Cookie的官方类。但是在各个App的实际开发过程中,给HTML5后台传入Cookie进行身份校验等属于最最基本的操作,不可能按照苹果的设想去进行。也正是因为不能方便设置Cookie的原因,在本文发布的时候,很多大厂App的核心web业务并没有使用WKWebView,仍然是UIWebView。iOS11开始,苹果意识到了这个问题,做了妥协,新增WKHTTPCookieStorage来帮助开发者解决Cookie问题,虽然方便了,但是API仍然不稳定,比如iOS11.3的时候就出现了一些变动。具体Cookie到底是什么,然后项目中解决Cookie的步骤,我单独写了两篇文章来详细说明。《39- WKWebView项目实践分享(四) - 先了解下Cookie》《WKWebView项目实践分享(五)- WKWebView如何加Cookie》

  • NSURLProtocol: 黑魔法在WKWebView是不被苹果所允许的,网上有调用私有API来获取和实现NSURLProtocol的方法,虽然可以实现其部分功能,但是仍然有很多问题和风险。我在后续接入WKWebView的过程中,直接舍弃了NSURLProtocol

下图是CookieNSURLProtocol在iOS11.3及其以前版本中存在的问题:

WKWebView中的`Cookie`和`NSURLProtocol`

其它需要注意的地方:

  • 有的webView页面出现偏移
  • 需要自己处理AlertView弹框
  • 需要自己处理a标签和target=_blank
  • 页面的重定向
  • 跳转到支付宝、打电话、打开Appstore等需要自己处理openURL:
  • OC调用JS的方法是异步的
  • 修改User-Agent
  • 跨域请求
  • 白屏问题

当然了,还有其它需要注意的地方,上边只是在我的应用中遇到的和解决的。关于其它大家可以自行网上搜索或者看我最下边提供的参考文章的链接。
在下一篇文章里,我结合自己项目来说说基于当前iOS11.3下是如何解决这些问题的。


WebKit介绍

UIWebView属于UIKit框架,而WKWebView属于独立的WebKit框架。这个框架中的所有API都和webView有关。从这里也可以看出,WKWebVie拥有的API是非常丰富的,你能更加细致的把控webView的展示和交互过程。


UIWebView
WKWebView
UIWebView只有一个类
WebKit丰富的API

另外,WKWebView的结构和UIWebView的结构不同,如下:

WKWebView的结构和UIWebView的结构对比(图来自网上)

WkWebView常用API概览

下图中,是WkWebView所涉及到的相关类及其作用:


相关类介绍

下图中,对上图中的类按照功能作用进行柜类,可以分为如下几种:


按功能划分1
按功能划分2

WkWebView简单使用和说明

1. WKWebViewConfiguration和初始化
相较于UIWebView,WKWebView在初始化的时候可以传入一个WKWebViewConfiguration对象。这个WKWebViewConfiguration的作用是对WKWebView进行相关设置,比如,你可以设置否进行在线自动播放、复制内容的精确度、给webView添加JS代码等
以下几行代码,你就可以正常显示一个webView,如下:

WKWebViewConfiguration *configuration =  [[WKWebViewConfiguration alloc] init];
// ...这里可以进行设置 configuration.xxx = xxxx;
WKWebView *webView = [[WKWebView alloc] initWithFrame:myFrame configuration:configuration];

NSURL *URL = [NSURL URLWithString:@"https://www.baidu.com"]; 
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
[webView loadRequest:request];
多个WKWebView可以对应一个configuration, 也可以各自单独对应

如果要进行额外的设置,在WKWebViewConfiguration中可能用到的一些类以及其作用,如下:

WKWebViewConfiguration中的一些相关设置类

2. WKWebView的三大代理

WKWebView的三大代理

使用代码如下:

wkWebView.navigationDelegate = self; // WKNavigationDelegate
wkWwebView.UIDelegate = self; // WKUIDelegate
 //...WKScriptMessageHandler的使用,在后续中文章专门讲解
  • WKNavigationDelegate
    先说一下WKNavigationDelegate,它提供了WKWebView在整个加载过程中不同阶段【比如开始加载、正在加载、加载成功、加载失败等】的回调方法。回调方法很多,可以让我们掌控webView更多的加载细节,然后对其加载过程进行干预。
    下面两图中,我们可以看出WKWebView和UIWebView相比,新增加了哪些阶段可以被开发者所操作:
来自:2104-WWDC

左:UIWebView,右:WKWebView -《教你使用 WKWebView 的正确姿势》

下图是在webView请求过程中,WKNavigationDelegate提供的方法和UIWebView代理方法的区别:

加载过程中的回调方法

另外,WKNavigationDelegate还有两个重要的代理方法如下:

  //  当WKWebView对应进程退出时回调
  - (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView
  // 当一个正在提交的页面在跳转过程中出现错误时调用这个方法
 - (void)webView:(WKWebView *)didFailNavigation:(WKNavigation *) withError:(NSError *)
  • WKUIDelegate


    WKUIDelegate方法
  • WKScriptMessageHandler

3. 方法的参数解释
上边我们已经介绍了WKWebViewConfiguration的相关属性,在这里再介绍一下WKUIDelegate和WKNavigationDelegate中的其它的一些参数,以帮助我们更好理解WKWebView的设计意图的使用它。

  • WKFrameInfo
    包含了一个网页页面的框架frame信息:
    • mainFrame:是否是主窗口(框架)
    • request:窗口(框架)的请求
    • securityOrigin:框架的安全源
    • webView:WkWebView
  • 拓展:关于HTML中的frame
HTML中的frame

这里是从 W3CSchool得到的一些信息,如果像更多的了解frame,可以查一下W3CSchool:

  • <frameset> 标签:每个框架都可以设置不同的属性,比如 border、scrolling、noresize 等等
  • <frame> 标签:定义 frameset 中的一个特定的窗口(子窗口)(框架)
  • 但是由于<frame> 标签对网页可用性的负面影响,在 HTML 5 中 <frame> 标签没有得到支持

通过WKFrameInfo,可以得到【当前frame是不是当前HTML页面的主frame】等信息。

  • WKNavigationAction
    WKNavigationAction类中包括的属性

    WKNavigationAction存在的方法之一是decidePolicyForNavigationAction:,该方法是webView刚开始准备向服务器发起请求的时候被调用。其中的几个属性的作用如下:
    - 通过request我们可以得到发起的请求的信息,包括HttpHeader、cookie、User Agent等。
    - 通过navigationType我们可以来判断进入当前回调方法的操作是返回上一页,还是前进到下一页,还是重新刷新或者新加载一个URL等。
    - 通过sourceFrame和targetFrame(destinationFrame)可以得到当次请求来自的HTML页面的frame的信息。
  • WKNavigationResponse
    WKNavigationResponse类中包括的属性

    WKNavigationResponse是在webView请求发送到服务器,然后服务器做出了响应,App接收到响应之后调用的方法decidePolicyForNavigationResponse:中。 通过其中的NSURLResponse可以得到请求回调的内容。
  • Decision Handle(请求决策者)
    下边这两个方法是发起请求前和收到请求后的回调:

    -(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler  
    -(void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
    

两个方法中参数block(void (^)(WKNavigationResponsePolicy))decisionHandler的作用是是否继续执行后续请求流程。
在UIWebView中,判断是否执行当前webView的请求是在shouldStartLoadWithRequest:方法中,我们通过返回YES或者NO来决定。 在WKWebView中,在请求发起之前和接收到服务器返回的方法中都可以判断当前的webView是否是自己想要的,是否继续执行请求。

  • WKNavigationActionPolicyCancel 停止继续请求
  • WKNavigationActionPolicyAllow 继续请求
  • WKNavigationResponsePolicyCancel
  • WKNavigationResponsePolicyAllow
  • WKUserScript 我们在后续单独的文章专门讲解。

参考

交流


希望能和大家交流技术
Blog:http://www.lilongcnc.cc


·

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345