WKWebView

概述:在iOS8中加入,用来替代UIWebView的控件。比UIWebView加载快一倍的控件,内存方面却比UIWebView少一半,但是相对的缓存处理方面会稍微差一点;

优缺点:
优点:
1)、将浏览器内核渲染进程提取出 App,由系统进行统一管理,这减少了相当一部分的性能损失。
2)、js 可以直接使用已经事先注入 js runtime 的 js 接口给 Native 层传值,不必再通过苦逼的 iframe 制造页面刷新再解析自定义协议的奇怪方式。
3)、支持高达 60 fps 的滚动刷新率,内置了手势探测。
4)、支持了更多的HTML5特性。
缺点:
1)、WK对缓存和Cookie操作没有UIWebView那么方便。(调用的API没有那么显著的用途。)
2)、WK从iOS8才开始支持,也就是说在我们同时对iOS7支持的情况下,如果为了减少代码量及适配等方面因素,一样会选择UIWebView。
3)、WkWebView不可以实现NSURLProtocol 拦截

分析一下UIWebView缓存机制
1、NSURLRequestUseProtocolCachePolicy NSURLRequest默认的cache policy,使用Protocol协议定义。
2、NSURLRequestReloadIgnoringCacheData 忽略缓存直接从原始地址下载。
3、NSURLRequestReturnCacheDataElseLoad 只有在cache中不存在data时才从原始地址下载。
4、NSURLRequestReturnCacheDataDontLoad 只使用cache数据,如果不存在cache,请求失败;用于没有建立网络连接离线模式;
5、NSURLRequestReloadIgnoringLocalAndRemoteCacheData:忽略本地和远程的缓存数据,直接从原始地址下载,与NSURLRequestReloadIgnoringCacheData类似。
6、NSURLRequestReloadRevalidatingCacheData:验证本地数据与远程数据是否相同,如果不同则下载远程数据,否则使用本地数据。

Notes:
The WebKit framework is not thread-safe. If you call functions or methods in this framework, you must do so exclusively on the main program thread.

UIWebView回顾:

UIWebView详细总结

WKWebView:

WKWebview属性:

新增属性:

// UIWebView 中会自动保存Cookie,如果登录了一次下次再次进入的时候,会记住登录状态 
// 在WKWebView中,新增一个configuration属性, configuration 让WKWebView知道登录状态,configuration 可以通过已有的Cookie进行设置,也可以通过保存上一次的configuration进行设置 
// WKWebViewConfiguration类中也有一些相应的属性
@property (nonatomic, readonly, copy) WKWebViewConfiguration *configuration;

//WKWebView中,加入了网站导航的概念,这个对象决定主框架导航加载方法协议
@property (nullable, nonatomic, weak) id <WKNavigationDelegate> navigationDelegate;

// WKWebView中,加入了网站窗口的概念,这个对象决了webView窗口的一些方法协议。
@property (nullable, nonatomic, weak) id <WKUIDelegate> UIDelegate;

// WKWebView中,加入了网站列表的概念,这个WEBBackForwardList对象是以前在Web视图访问的网页,可以通过去后退或前进
@property (nonatomic, readonly, strong) WKBackForwardList *backForwardList;

//WKWebView新加入了一次请求的进度的属性,新的Request会重置上次请求的进度
//[_wkWebView addObserver:self forKeyPath:NSStringFromSelector(@selector(estimatedProgress)) options:0 context:WkwebBrowserContext];
@property (nonatomic, readonly) double estimatedProgress;

@property (nonatomic, readonly) BOOL hasOnlySecureContent;

@property (nonatomic, readonly, nullable) SecTrustRef serverTrust API_AVAILABLE(macosx(10.12), ios(10.0));

// 新增了左滑右滑的手势
@property (nonatomic) BOOL allowsBackForwardNavigationGestures;


@property (nullable, nonatomic, copy) NSString *customUserAgent API_AVAILABLE(macosx(10.11), ios(9.0));

@property (nonatomic) BOOL allowsLinkPreview API_AVAILABLE(macosx(10.11), ios(9.0));

WKWebView的方法:

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

- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;

- (nullable WKNavigation *)loadRequest:(NSURLRequest *)request;

- (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL API_AVAILABLE(macosx(10.11), ios(9.0));

- (nullable WKNavigation *)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;

- (nullable WKNavigation *)loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL API_AVAILABLE(macosx(10.11), ios(9.0));

- (nullable WKNavigation *)goBack;

- (nullable WKNavigation *)goForward;

- (nullable WKNavigation *)reload;

新增方法:

// 前进或者后退到某页
- (nullable WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item;

//重新加载原始URL,会比较网络数据是否有变化,没有变化则使用缓存,否则从新请求
- (nullable WKNavigation *)reloadFromOrigin;

/*! @abstract Stops loading all resources on the current page.
 */
- (void)stopLoading;

// Native通过该方法调用JavaScript,completionHandler执行的回调结果
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;

//根据设置的缩放率来缩放页面,并居中显示结果在指定的点
- (void)setMagnification:(CGFloat)magnification centeredAtPoint:(CGPoint)point;

WKWebView相关协议:

1)、WKScriptMessageHandler
提供接收网页JS调用的方法


//拦截执行网页中的JS方法
//服务器固定格式写法 window.webkit.messageHandlers.名字.postMessage(内容);
//客户端写法 message.name isEqualToString:@"名字"]
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;

2)、WKNavigationDelegate
可以用来追踪加载过程(页面开始加载、加载完成、加载失败)、决定是否执行跳转,还能监听服务器跳转、身份认证等

a、页面开始加载、加载完成、加载失败

//页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation;

//当内容开始返回时调用
- (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation;

//页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation;

// 页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error;

b、页面跳转的代理方法有三种,分为(收到跳转与决定是否跳转两种)

//接收到服务器跳转请求之后调用
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation;

// 发送请求之前,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;

//在收到响应后,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;

c、导航错误、身份认证、webview进程终止


//WKNavigation导航错误
- (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error;

// 身份验证
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler;

//WKWebView进程终止,9.0以后才能使用
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView API_AVAILABLE(macosx(10.11), ios(9.0));

3)、WKUIDelegate
作用:通过该协议,展示本地UI,如AlertView等

// 创建一个新的wkWebview
- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;
- (void)webViewDidClose:(WKWebView *)webView API_AVAILABLE(macosx(10.11), ios(9.0));

界面弹出提示框相关

// 获取js 里面的提示
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;

// js 信息的交流
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler;

// 交互。可输入的文本。
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler;

iOS10 新增3D touch API
用户在WKWebView中使用3D Touch查看和弹出链接就可以显示自定义视图控制器

//当用户触摸元素时webView(_:shouldPreviewElement:)立即被调用。返回NO将完全禁用该元素的预览,并且阻止其他方法的调用。返回YES将提供一个自定义视图控制的机会,前提是用户触摸时有足够的力度来启动查看
- (BOOL)webView:(WKWebView *)webView shouldPreviewElement:(WKPreviewElementInfo *)elementInfo API_AVAILABLE(ios(10.0));

//如果用户输入Peek,那么webView(_:previewingViewControllerForElement:defaultActions:)为其提供了一个定制视图控制器的机会。返回任何非空视图控制器都会导致视图控制器显示为Peek预览。defaultActions参数是一个活动数组,WebKit Webkit默认使用它作为previewActionItems。如果想要使用这些活动中的任何一个,你只需从视图控制器的previewActionItems执行结果中返回即可
- (nullable UIViewController *)webView:(WKWebView *)webView previewingViewControllerForElement:(WKPreviewElementInfo *)elementInfo defaultActions:(NSArray<id <WKPreviewActionItem>> *)previewActions API_AVAILABLE(ios(10.0));

// 用户用足够的力触摸来弹出视图控制器,webView(_:commitPreviewingViewController:)将被调用。此时,你可以选择在app中展示弹出的视图控制器
- (void)webView:(WKWebView *)webView commitPreviewingViewController:(UIViewController *)previewingViewController API_AVAILABLE(ios(10.0));

WKWebView更好的与Web交互

回顾UIWebView的方式:

  1. delegate方法webViewDidFinishLoad中注入JS源码
NSString *js = @"js代码";
[webView stringByEvaluatingJavaScriptFromString:js];
  1. 调用native方法
当html调用这段注入的JS方法后,会将hybrid://invoke? 以及后面拼接的内容以IFrame的方式进行加载,在加载的同时会出发APP的delegate方法
在shouldStartLoadWithRequest方法中解析:

NSString *url = request.URL.absoluteString;
    if(url != nil && [url hasPrefix:@"hybrid://invoke?"]){
        
        return NO;
    }

WKWebView -- Web 调 APP
1.在webview初始化之前先注册一个名为hybridDemo的handler对象。

WKWebViewConfiguration *config =[[WKWebViewConfiguration alloc]init];

[config.userContentController addScriptMessageHandler:self name:@"webViewApp"];

webView = [[WKWebView alloc]initWithFrame:self.view.bounds configuration:config];

2.在html端调用JS来访问之前注册的handler对象,并通过调用postMessage方法把数据传到app。

var message = {"method":"hello","args":"let go"};

window.webkit.messageHandlers.webViewApp.postMessage(message);

3.在webview容器中实现上文提过的WKScriptMessageHandler委托,从而响应来自于JS端下发的message

//拦截执行网页中的JS方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    
    //服务器固定格式写法 window.webkit.messageHandlers.名字.postMessage(内容);
    //客户端写法 message.name isEqualToString:@"名字"]
    [XYWebViewEventService executeWithEventId:message.name paramater:message.body];
   
}
// 图片缩放的js代码
NSString *js = @"var count = document.images.length;for (var i = 0; i < count; i++) {var image = document.images[i];image.style.width=320;};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];
WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
 [_webView loadHTMLString:@"<head></head>![](http://upload-images.jianshu.io/upload_images/2344965-67a790ebf8cdb9e4.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)"baseURL:nil];
[self.view addSubview:webView];
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容