iOS 加载webView进度条

作者: 倚楼听风雨wing | 来源:发表于2016-07-22 17:19 被阅读12755次
    webViewLoading.gif

    简介##

    为了项目的敏捷性和简单性,现在的app常常会嵌入不少的H5页面,而如何优雅的显示这些web页面呢,我这里参照微信显示web页面的方式,做了一个导航栏下的加载进度条.因为项目最低支持iOS7,所以不能使用WKWebView来加载网页,只能使用 UIWebView,查看 UIWebView的API可以发现,并没有代理或是通知告诉我们webView加载了多少,所以这个进度条我决定用虚拟的方式来做,就是假装知道加载了多少.

    加载WebView的控制器WYWebController

    @interface WYWebController : UIViewController
    
    @property (nonatomic, copy) NSString *url;
    
    @end
    
    
    #import "WLWebController.h"
    #import "WLWebProgressLayer.h"
    #import "UIView+Frame.h"
    
    @interface WLWebController ()<UIWebViewDelegate>
    
    @end
    
    @implementation WLWebController
    {
        UIWebView *_webView;
        
        WLWebProgressLayer *_progressLayer; ///< 网页加载进度条
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        self.view.backgroundColor = [UIColor whiteColor];
        [self setupUI];
    }
    
    - (void)setupUI {
        _webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
        _webView.delegate = self;
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:self.url]];
        [_webView loadRequest:request];
        
        _webView.backgroundColor = [UIColor whiteColor];
        
        _progressLayer = [WLWebProgressLayer new];
        _progressLayer.frame = CGRectMake(0, 42, SCREEN_WIDTH, 2);
        
        [self.navigationController.navigationBar.layer addSublayer:_progressLayer];
        [self.view addSubview:_webView];
    }
    
    #pragma mark - UIWebViewDelegate
    /// 网页开始加载
    - (void)webViewDidStartLoad:(UIWebView *)webView {
        [_progressLayer startLoad];
    }
    
    /// 网页完成加载
    - (void)webViewDidFinishLoad:(UIWebView *)webView {
        [_progressLayer finishedLoad];
    
    // 获取h5的标题
        self.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
        
    }
    
    /// 网页加载失败
    - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
        [_progressLayer finishedLoad];
    }
    
    - (void)dealloc {
        
        [_progressLayer closeTimer];
        [_progressLayer removeFromSuperlayer];
        _progressLayer = nil;
        NSLog(@"i am dealloc");
    }
    
    @end
    
    

    进度条WYWebProgressLayer.h

    #define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width
    
    @interface WYWebProgressLayer : CAShapeLayer
    
    - (void)finishedLoad;
    - (void)startLoad;
    
    - (void)closeTimer;
    
    @end
    

    WYWebProgressLayer.m这个类主要继承自CAShapeLayer,这里我主要想要使用CAShaperLayerstrokeStart[默认0]和strokeEnd[默认1]这两个属性来对进度条进行渲染,使用定时器更改strokeEnd的值使其看起来就像在一点一点的加载一样.

    #import "WYWebProgressLayer.h"
    #import "NSTimer+addition.h"
    
    static NSTimeInterval const kFastTimeInterval = 0.003;
    
    @implementation WYWebProgressLayer {
       CAShapeLayer *_layer;
       
       NSTimer *_timer;
       CGFloat _plusWidth; ///< 增加点
    }
    
    - (instancetype)init {
       if (self = [super init]) {
           [self initialize];
       }
       return self;
    }
    
    - (void)initialize {
       self.lineWidth = 2;
       self.strokeColor = [UIColor greenColor].CGColor;
       
       _timer = [NSTimer scheduledTimerWithTimeInterval:kFastTimeInterval target:self selector:@selector(pathChanged:) userInfo:nil repeats:YES];
       [_timer pause];
       
       UIBezierPath *path = [UIBezierPath bezierPath];
       [path moveToPoint:CGPointMake(0, 2)];
       [path addLineToPoint:CGPointMake(SCREEN_WIDTH, 2)];
       
       self.path = path.CGPath;
       self.strokeEnd = 0;
       _plusWidth = 0.01;
    }
    
    - (void)pathChanged:(NSTimer *)timer {
       self.strokeEnd += _plusWidth;
       
       if (self.strokeEnd > 0.8) {
           _plusWidth = 0.002;
       }
    }
    
    - (void)startLoad {
       [_timer resumeWithTimeInterval:kFastTimeInterval];
    }
    
    - (void)finishedLoad {
       [self closeTimer];
       
       self.strokeEnd = 1.0;
       dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
           self.hidden = YES;
           [self removeFromSuperlayer];
       });
    }
    
    - (void)dealloc {
    //    NSLog(@"progressView dealloc");
       [self closeTimer];
    }
    
    #pragma mark - private
    - (void)closeTimer {
       [_timer invalidate];
       _timer = nil; 
    }
    

    Demo:https://github.com/wangyansnow/WYWebViewDemo

    如何放到项目中用##

    只需要下载demo,然后把demo中的整个web文件夹拖入到项目中,使用方式例:

    WYWebController *webVC = [WYWebController new];
    webVC.url = @"https://www.baidu.com";
    [self.navigationController pushViewController:webVC animated:YES];
    

    相关文章

      网友评论

      • 奔跑吧小蚂蚁:HTTPS://QR.ALIPAY.COM/FKX018203OCQRKXWXFCL20 这里是我加载的网址 你加载一下试试 方法已经调用了加载完成 但是进度条依然保持着0.97的状态
        Espero:@倚楼听风雨wing 你对_progressLayer这个的初始化位置有问题,应该在viewdidload就得初始化了,不然在这个方法webViewDidStartLoad里会有问题。
        倚楼听风雨wing:不好意思,最近比较忙,现在才回复你,我试了,正常,你这个问题还存在吗
      • 奔跑吧小蚂蚁:l楼主我也有一个问题 加载一个网页 加载完成后我已经调用了 进度条完成 但是进度条一直没有消失 然后我手动移除依然没有移除掉
      • 丨Majestic灬磊:我按照你的方法 直接 不能跳转 !直接走dealloc。打印I am dealloc
        倚楼听风雨wing:不能跳转,直接走dealloc,你到github下载我的demo试试,肯定有什么地方设置不一样,如果还是有问题,你可以把你的demo发给我,我给你看看
      • 天天简友:为什么我添加进我的项目里面,调用了之后progressLayer立马调用dealloc了。。。
        倚楼听风雨wing:@3f00072262e9 你的问题我看了,现在已经修复了这个问题,并且上传最新版本到github。每次在改变layer的strokeEnd的时候关闭隐式动画就不会调dealloc了。
        天天简友:@倚楼听风雨wing 是在我自己的webviewController里使用的progressLayer,用的webview是继承自UIWebview的,progressLayer里的dealloc会调好多次,但是调用dealloc之后还能正常显示。。。醉了,我现在把progressLayer里的dealloc删了,在其他地方closetimer了
        倚楼听风雨wing:可否写得详细一点,你是直接使用的progressLayer,还是使用的WLWebController加载的h5
      • Icoder_e90d:([keyPath isEqualToString:@"estimatedProgress"])不是用这个判断进度条吗?
        Icoder_e90d:@倚楼听风雨wing 是的
        倚楼听风雨wing:你的意思是使用KVO监听"estimatedProgress"吗?
      • WSGNSLog:楼主这么写没有网络的情况下你的进度条也会走啊
        倚楼听风雨wing:@WSGNSLog 是的,0.5秒就走完
      • Aili_00:存在即合理
      • 清眸如画:不好吧
      • michaelxing:这个不合理吧
        sincere_bs:@倚楼听风雨wing 挺合理的 只是他们不知道,微信的进度条也是假的。不是像下载进度那样,可以获取currentSize和totalSize.
        倚楼听风雨wing:@michaelxing 什么地方不合理,请具体说明一下,我也好更正,谢谢
      • 我系哆啦:原来是假的

      本文标题:iOS 加载webView进度条

      本文链接:https://www.haomeiwen.com/subject/jppijttx.html