一个KVO 实现WKWebView加载进度条的例子 (注意最后移除观察者)

Posted liuw_flexi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个KVO 实现WKWebView加载进度条的例子 (注意最后移除观察者)相关的知识,希望对你有一定的参考价值。

//
//  OpenWebViewController.m
//  Treasure
//
//  Created by 蓝蓝色信子 on 16/7/29.
//  Copyright ? 2016年 GY. All rights reserved.
//

#import "ZTOpenWebViewController.h"
#import <WebKit/WebKit.h>

@interface ZTOpenWebViewController ()<WKNavigationDelegate>
//{
//    //网页视图
//    UIWebView * _webView;
//}
@property (strong, nonatomic) WKWebView *webView;


@property (strong, nonatomic) UIProgressView *progressView;

@end

@implementation ZTOpenWebViewController



- (void)viewDidLoad {
    [super viewDidLoad];
    //    //取消导航栏的影响
    self.automaticallyAdjustsScrollViewInsets = NO;
    self.view.backgroundColor = [UIColor whiteColor];
    
    //[SVProgressHUD show];
    //实例化
    [self createWebView];
    
    [self creatCustomProgressView];
}

-(void)creatCustomProgressView{
    
    //增加加载进度条
    // KVO,监听webView属性值得变化(estimatedProgress,title为特定的key)
    [_webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
    [_webView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:nil];
    
    // UIProgressView初始化
    self.progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
    self.progressView.frame = CGRectMake(0, 0, _webView.frame.size.width, 5);
    self.progressView.trackTintColor = [UIColor clearColor]; // 设置进度条的色彩
    self.progressView.progressTintColor = [UIColor magentaColor];
    // 设置初始的进度,防止用户进来就懵逼了(微信大概也是一开始设置的10%的默认值)
    [self.progressView setProgress:0.1 animated:YES];
    [_webView addSubview:self.progressView];
}

- (void)viewWillAppear:(BOOL)animated
{
    [self.navigationController setNavigationBarHidden:NO animated:NO];
    [super viewWillAppear:YES];
}
- (void)viewWillDisappear:(BOOL)animated
{
    [SVProgressHUD dismiss];
    [super viewWillDisappear:animated];
}

- (void)createWebView
{
    _webView = [[WKWebView alloc]initWithFrame:self.view.bounds];
    
    [self.view addSubview:_webView];
    
    //调整适应比例
    //_webView.scalesPageToFit = YES;
    //设置代理
    _webView.navigationDelegate = self;
    [[NSURLCache sharedURLCache] removeAllCachedResponses];
    [_webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.urlStr] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10.0]];
    
}
#pragma mark - WKWebView NavigationDelegate

//WKNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    //NSLog(@"是否允许这个导航");
    decisionHandler(WKNavigationActionPolicyAllow);
}

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
    //    Decides whether to allow or cancel a navigation after its response is known.
    
    //NSLog(@"知道返回内容之后,是否允许加载,允许加载");
    decisionHandler(WKNavigationResponsePolicyAllow);
}
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation {
    //NSLog(@"开始加载");
    //self.progress.alpha  = 1;
    
    //[SVProgressHUD show];
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    
}

- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation {
    //NSLog(@"跳转到其他的服务器");
    
}

- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {
    //NSLog(@"网页由于某些原因加载失败");
    //[SVProgressHUD dismiss];
    //self.progress.alpha  = 0;
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
- (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation {
    //NSLog(@"网页开始接收网页内容");
}
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
    //NSLog(@"网页导航加载完毕");
    //[SVProgressHUD dismiss];
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    
    self.title = webView.title;
    [webView evaluatejavascript:@"document.title" completionHandler:^(id _Nullable ss, NSError * _Nullable error) {
        //NSLog(@"----document.title:%@---webView title:%@",ss,webView.title);
    }];
    //self.progress.alpha  = 0;
    
}

- (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {
    //NSLog(@"加载失败,失败原因:%@",[error description]);
    //self.progress.alpha = 0;
}
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView {
    //NSLog(@"网页加载内容进程终止");
}


#pragma mark - KVO监听
// 第三部:完成监听方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    
    if ([object isEqual:_webView] && [keyPath isEqualToString:@"estimatedProgress"]) { // 进度条
        
        CGFloat newprogress = [[change objectForKey:NSKeyValueChangeNewKey] doubleValue];
        //NSLog(@"打印测试进度值:%f", newprogress);
        
        if (newprogress == 1) { // 加载完成
            // 首先加载到头
            [self.progressView setProgress:newprogress animated:YES];
            // 之后0.3秒延迟隐藏
            __weak typeof(self) weakSelf = self;
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
                
                weakSelf.progressView.hidden = YES;
                [weakSelf.progressView setProgress:0 animated:NO];
            });
            
        } else { // 加载中
            self.progressView.hidden = NO;
            [self.progressView setProgress:newprogress animated:YES];
        }
    } else if ([object isEqual:_webView] && [keyPath isEqualToString:@"title"]) { // 标题
        
        //self.title = _webView.title;
    } else { // 其他
        
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

-(void)dealloc{
    NSLog(@"webVC dealloc = %@",self);
    [_webView removeObserver:self forKeyPath:@"estimatedProgress"];
    [_webView removeObserver:self forKeyPath:@"title"];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
 #pragma mark - Navigation
 
 // In a storyboard-based application, you will often want to do a little preparation before navigation
 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
 // Get the new view controller using [segue destinationViewController].
 // Pass the selected object to the new view controller.
 }
 */

@end

 

以上是关于一个KVO 实现WKWebView加载进度条的例子 (注意最后移除观察者)的主要内容,如果未能解决你的问题,请参考以下文章

WKWebView进度及title

iOS获取WKWebView的高度

前端页面加载进度条的制作

网页加载进度条的实现

SwiftUI如何监听WKWebView加载网页的进度

WKWebView获取页面title和加载进度值