大家都知道iOS 8 之后,出了一个新的WKWebView,算是UIWebVeiw的升级版,对于它大家估计都有耳闻,下面先说一下它的一些优点:
- 性能高,稳定性好,占用的内存比较小
- 支持JS交互
- 支持HTML5 新特性
- 可以添加进度条
- 支持内建手势
- 据说高达60fps的刷新频率(不卡)
因为最近在搭建一个新项目框架,所以封装了一个webView的基类,下面把它粘出来,大家仅供参考:
.h
@property (nonatomic, strong) WKWebView *wkWebView;
@property (nonatomic, copy) NSString *loadUrl;
@property (nonatomic, strong) UIProgressView *progressView;```
.m类实现
- (void)viewDidLoad {
[super viewDidLoad];
[self addWebView];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc {
[self.wkWebView removeObserver:self forKeyPath:@"estimatedProgress"];
}
#pragma mark - webview初始化及加载
- (void)addWebView
{
/*
* wkWebView相关设置
*/
self.wkWebView = [[WKWebView alloc] initWithFrame:CGRectZero];
[self.wkWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.loadUrl]]];
//开启手势触摸
self.wkWebView.allowsBackForwardNavigationGestures = YES;
[self.view addSubview:self.wkWebView];
//适应你设定的尺寸
[self.wkWebView sizeToFit];
//设置约束
[self setupLayout];
//添加KVO,检测属性estimatedProgress(进度条)
[self.wkWebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
/*
* 进度条相关设置
*/
if(!self.progressView){
self.progressView=[[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleDefault];
self.progressView.frame=CGRectMake(0, 0, self.view.bounds.size.width, 2);
[self.progressView setTrackTintColor:[UIColor clearColor]];
self.progressView.progressTintColor=[UIColor redColor];
[self.view addSubview:self.progressView];
}
}
#pragma mark - 设置wkWebview约束
- (void)setupLayout
{
[self.wkWebView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.bottom.mas_equalTo(self.view);
make.top.mas_equalTo(self.view.mas_top).with.offset(0);
}];
}
#pragma mark - 检测加载进度
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
if ([keyPath isEqualToString:@"estimatedProgress"]) {
self.progressView.progress = self.wkWebView.estimatedProgress;
if (self.progressView.progress == 1) {
/*
*添加一个简单的动画,将progressView的Height变为1.4倍,在开始加载网页的代理中会恢复为1.5倍
*动画时长0.25s,延时0.3s后开始动画
*动画结束后将progressView隐藏
*/
__weak typeof (self)weakSelf = self;
[UIView animateWithDuration:0.25f delay:0.3f options:UIViewAnimationOptionCurveEaseOut animations:^{
weakSelf.progressView.transform = CGAffineTransformMakeScale(1.0f, 1.4f);
} completion:^(BOOL finished) {
weakSelf.progressView.hidden = YES;
}];
}
}else{
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
#pragma mark - WKNavigationDelegate
// 页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation
{
NSLog(@"开始加载网页");
//开始加载网页时展示出progressView
self.progressView.hidden = NO;
//开始加载网页的时候将progressView的Height恢复为1.5倍
self.progressView.transform = CGAffineTransformMakeScale(1.0f, 1.5f);
//防止progressView被网页挡住
[self.view bringSubviewToFront:self.progressView];
}
// 当内容开始返回时调用
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation
{
}
// 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
NSLog(@"加载完成");
//加载完成后隐藏progressView
self.progressView.hidden = YES;
}
// 页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation
{
NSLog(@"加载失败");
//加载失败同样需要隐藏progressView
self.progressView.hidden = YES;
}
// 接收到服务器跳转请求之后再执行
- (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
{
}
#pragma mark - WKUIDelegate
//WebVeiw关闭(9.0中的新方法)
- (void)webViewDidClose:(WKWebView *)webView NS_AVAILABLE(10_11, 9_0)
{
}
//显示一个JS的Alert(与JS交互)
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
}
//弹出一个输入框(与JS交互的)
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler
{
}
//显示一个确认框(JS的)
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler
{
}
#pragma mark - WKScriptMessageHandler
// 从web界面中接收到一个脚本时调用
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
}
使用的时候,仅需继承于这个基类,建一个viewController传入,loadUrl就可以实现webview加载了,当然里面没有写到JS交互相关的,后续有相关需求的时候再继续优化更新!希望可以帮到大家!