iOS开发 WKWebView的使用
本文将讲解到WebKit中更新的WKWebView控件的新特性与使用方法,它很好的解决了UIWebView存在的内存、加载速度等诸多问题
webkit使用WKWebView来代替IOS的UIWebView和OSX的WebView,并且使用Nitro JavaScript引擎,这意味着所有第三方浏览器运行JavaScript将会跟safari一样快。
第一、WKWebView增加的属性和方法
类比UIWebView,跟UIWebView的API对比,
增加的属性:
1、estimatedProgress 加载进度条,在IOS8之前我们是通过一个假的进度条来实现
2、backForwardList 表示historyList
3、WKWebViewConfiguration *configuration; 初始化webview的配置
增加的方法:
1、- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration
初始化
3、(WKNavigation )goToBackForwardListItem:(WKBackForwardListItem )item;
跳到历史的某个页面
第二、相同的属性和方法
goBack、goForward、canGoBack、canGoForward、stopLoading、loadRequest、scrollView
第三、被删去的属性和方法:
1、- (NSString )stringByEvaluatingJavaScriptFromString:(NSString )script;
在跟js交互时,我们使用这个API,目前WKWebView完档没有给出实现类似功能的API
2、无法设置缓存
在UIWebView,使用NSURLCache缓存,通过setSharedURLCache可以设置成我们自己的缓存,但WKWebView不支持NSURLCache
第四、delegate方法的不同
UIWebView支持的代理是UIWebViewDelegate,WKWebView支持的代理是WKNavigationDelegate和WKUIDelegate
WKNavigationDelegate主要实现了涉及到导航跳转方面的回调方法
WKUIDelegate主要实现了涉及到界面显示的回调方法:如WKWebView的改变和js相关内容
具体来说WKNavigationDelegate除了有开始加载、加载成功、加载失败的API外,还具有额外的三个代理方法:
1、- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation
这个代理是服务器redirect时调用
2、- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
这个代理方法表示当客户端收到服务器的响应头,根据response相关信息,可以决定这次跳转是否可以继续进行。
3.- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
根据webView、navigationAction相关信息决定这次跳转是否可以继续进行,这些信息包含HTTP发送请求,如头部包含User-Agent,Accept
WKWebView中的三个代理方法
- 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 didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation;
// 在收到响应后,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;
// 在发送请求之前,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
- WKUIDelegate
创建一个新的WKWebView
// 创建一个新的WebView
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;
剩下三个代理方法全都是与界面弹出提示框相关的,针对于web界面的三种提示框(警告框、确认框、输入框)分别对应三种代理方法。
// 界面弹出警告框
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(void (^)())completionHandler;
// 界面弹出确认框
- (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;
- WKScriptMessageHandler
这个协议中包含一个必须实现的方法,这个方法是native与web端交互的关键,它可以直接将接收到的JS脚本转为OC或Swift对象。
// 从web界面中接收到一个脚本时调用
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
开发中WKWebView的使用
//
// RuleController.h
//
// Created by zhouyu on 16/10/3.
// Copyright © 2016年 mac All rights reserved.
//
#import <UIKit/UIKit.h>
@interface RuleController : UIViewController
@end
//
// RuleController.m
//
// Created by zhouyu on 16/10/3.
// Copyright © 2016年 mac All rights reserved.
//
#import "RuleController.h"
#import <WebKit/WebKit.h>
@interface RuleController ()<UINavigationBarDelegate,WKUIDelegate>
@property (weak, nonatomic) WKWebView *ruleWebView;
@property (nonatomic,strong) UIProgressView *progress;
@property (nonatomic,weak) UIActivityIndicatorView *loadStatusIndicator;
@end
@implementation RuleController
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.navigationController.navigationBar.hidden = NO;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"规则";
self.view.backgroundColor = [UIColor whiteColor];
WKWebView *ruleWebView = [[WKWebView alloc] init];
ruleWebView.frame = self.view.frame;
[self.view addSubview:ruleWebView];
self.ruleWebView = ruleWebView;
// 展示进度
self.progress = [[UIProgressView alloc] init];
self.progress.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 10);
[self.view addSubview:self.progress];
self.progress.progress = 0;
UIActivityIndicatorView *loadStatusIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
loadStatusIndicator.center = self.view.center;
loadStatusIndicator.bounds = CGRectMake(0, 0, 40, 40);
[self.view addSubview:loadStatusIndicator];
self.loadStatusIndicator = loadStatusIndicator;
// 添加监听
[ruleWebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
NSURL *URL = [NSURL URLWithString:@"http://www.baidu.com"];
self.ruleWebView.navigationDelegate = self;
[self.ruleWebView loadRequest:[NSURLRequest requestWithURL:URL]];
}
#pragma mark - 监听进度
// 计算wkWebView进度条
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (object == self.ruleWebView && [keyPath isEqualToString:@"estimatedProgress"]) {
CGFloat newprogress = [[change objectForKey:NSKeyValueChangeNewKey] doubleValue];
if (newprogress != 1.000000) {
self.progress.hidden = NO;
self.progress.progress = newprogress;
[self.loadStatusIndicator startAnimating];
} else {
// 网页加载完成就进度
self.progress.hidden = YES;
[self.loadStatusIndicator stopAnimating];
}
}
}
// 记得取消监听
- (void)dealloc
{
[self.ruleWebView removeObserver:self forKeyPath:@"estimatedProgress"];
}
@end