美文网首页
IOS WKWebView 和webView简单封装

IOS WKWebView 和webView简单封装

作者: MrLiangC | 来源:发表于2018-02-07 23:29 被阅读315次
    • wkwebView和webview可直接继承使用,也可直接使用
      .h
    #import "BaseViewController.h"
    #import <WebKit/WKWebView.h>
    #import <WebKit/WebKit.h>
    
    @interface LCWebViewController : BaseViewController<UIWebViewDelegate,WKNavigationDelegate,WKUIDelegate,UIGestureRecognizerDelegate>
    
    //请求地址
    @property (nonatomic, copy) NSString *url;
    
    @property (nonatomic, strong) WKWebView *wk_WebView;
    @property (nonatomic, strong) UIWebView *webView;
    
    @property (nonatomic, strong) UIBarButtonItem *backBarButtonItem;
    @property (nonatomic, strong) UIBarButtonItem *closeBarButtonItem;
    
    @property (nonatomic, strong) id <UIGestureRecognizerDelegate>delegate;
    //刷新控件
    @property (nonatomic, strong) UIRefreshControl *refreshControl;
    //加载进度条
    @property (nonatomic, strong) UIProgressView *loadingProgressView;
    //重新加载
    @property (nonatomic, strong) UIButton *reloadButton;
    //是否需要下拉刷新控件
    @property (nonatomic, assign) BOOL canDownRefresh;
    //加载时的小菊花
    @property (nonatomic, strong) UIActivityIndicatorView *indicatorView;
    //是否自动加载链接,默认为YES
    @property (nonatomic, assign) BOOL canAutoLoadRequest;
    
    - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
    - (void)webViewDidFinishLoad:(UIWebView *)webView;
    //子控制器可自行条用加载请求
    - (void)loadRequest;
    
    @end
    

    .m

    
    #import "LCWebViewController.h"
    
    static CGFloat const NAVI_HEIGHT = 0;
    
    @interface LCWebViewController ()
    
    @end
    
    @implementation LCWebViewController
    
    - (instancetype)init {
        if (self = [super init]) {
            //自动加载网页
            self.canAutoLoadRequest = YES;
        }
        
        return self;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        [self createWebView];
        [self createNaviItem];
        
        if (self.canAutoLoadRequest) {
            [self loadRequest];//加载网络请求
        }
    }
    
    - (void)dealloc {
        [_wk_WebView removeObserver:self forKeyPath:@"estimatedProgress"];
    }
    
    #pragma mark action
    //刷新
    - (void)webViewReload {
        self.reloadButton.hidden = YES;
        [_webView reload];
        [_wk_WebView reload];
    }
    
    //关闭按钮
    - (void)close:(UIBarButtonItem*)item {
        [self.navigationController popViewControllerAnimated:YES];
    }
    //返回按钮
    - (void)back:(UIBarButtonItem*)item {
        if ([_webView canGoBack] || [_wk_WebView canGoBack]) {
            [_webView goBack];
            [_wk_WebView goBack];
        } else {
            [self.navigationController popViewControllerAnimated:YES];
        }
    }
    
    //监听加载进度
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
        if ([keyPath isEqualToString:@"estimatedProgress"]) {
            
            NSLog(@"%f",[change[@"new"] floatValue]);
            //        _loadingProgressView.progress = [change[@"new"] floatValue];
            
            [self.loadingProgressView setProgress:[change[@"new"] floatValue] animated:YES];
            if (_loadingProgressView.progress == 1.0) {//加载完成
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                    _loadingProgressView.hidden = YES;
                });
            }
        }
    }
    
    #pragma mark 加载请求
    - (void)loadRequest {
        NSLog(@"loadURL is %@", self.url);
        if (![self.url hasPrefix:@"http"]) {//是否具有http前缀
            self.url = [NSString stringWithFormat:@"http://%@",self.url];
        }
        //防止url有特殊字符
        NSURL *url = [NSURL URLWithString:[self.url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
        if ([[[UIDevice currentDevice]systemVersion]floatValue] >= 8.0) {
            [_wk_WebView loadRequest:[NSURLRequest requestWithURL:url]];
        } else {
            [_webView loadRequest:[NSURLRequest requestWithURL:url]];
        }
    }
    
    #pragma mark - WebViewDelegate
    //开始加载
    - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
        webView.hidden = NO;
        [_indicatorView startAnimating];
        // 不加载空白网址
        if ([request.URL.scheme isEqual:@"about"]) {
            webView.hidden = NO;
            return NO;
        }
        return YES;
    }
    
    //加载完成
    - (void)webViewDidFinishLoad:(UIWebView *)webView {
        //导航栏配置
        //    self.navigationItem.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
        [_indicatorView stopAnimating];
        [self showLeftBarButtonItem];
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
        [_refreshControl endRefreshing];
    }
    //加载失败
    - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
        [_indicatorView stopAnimating];
        webView.hidden = NO;
        self.reloadButton.hidden = NO;
    }
    
    #pragma mark - WKNavigationDelegate
    
    #pragma mark 加载状态回调
    //页面开始加载
    - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation{
        webView.hidden = NO;
        [_indicatorView startAnimating];
        _loadingProgressView.hidden = NO;
        if ([webView.URL.scheme isEqual:@"about"]) {
            webView.hidden = NO;
        }
    }
    
    //页面加载完成
    - (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation{
        //导航栏配置
        //    [webView evaluateJavaScript:@"document.title" completionHandler:^(id _Nullable title, NSError * _Nullable error) {
        //        self.navigationItem.title = title;
        //    }];
        
        [self showLeftBarButtonItem];
        [_indicatorView stopAnimating];
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
        
        [_refreshControl endRefreshing];
    }
    
    //页面加载失败
    - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error{
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
        [_indicatorView stopAnimating];
        webView.hidden = NO;
        self.reloadButton.hidden = NO;
    }
    
    #pragma mark setupUI
    
    - (void)createWebView {
        self.view.backgroundColor = [UIColor whiteColor];
        self.automaticallyAdjustsScrollViewInsets = NO;
        if ([[[UIDevice currentDevice] systemVersion]floatValue] >= 8.0) {
            [self.view addSubview:self.wk_WebView];
            [self.wk_WebView addSubview:self.indicatorView];
            [self.indicatorView mas_makeConstraints:^(MASConstraintMaker *make) {
                make.size.mas_equalTo(CGSizeMake(60, 60));
                make.center.equalTo(self.wk_WebView);
            }];
            [self.view addSubview:self.loadingProgressView];
            [self.wk_WebView addSubview:self.reloadButton];
            [self.reloadButton mas_makeConstraints:^(MASConstraintMaker *make) {
                make.size.mas_equalTo(CGSizeMake(60, 60));
                make.center.equalTo(self.wk_WebView);
            }];
            
        }else {
            [self.view addSubview:self.webView];
            [self.webView addSubview:self.indicatorView];
            [self.indicatorView mas_makeConstraints:^(MASConstraintMaker *make) {
                make.size.mas_equalTo(CGSizeMake(150, 150));
                make.center.equalTo(self.webView);
            }];
            [self.reloadButton mas_makeConstraints:^(MASConstraintMaker *make) {
                make.size.mas_equalTo(CGSizeMake(150, 150));
                make.center.equalTo(self.wk_WebView);
            }];
        }
    }
    
    #pragma mark -- 导航按钮
    - (void)createNaviItem {
        [self showLeftBarButtonItem];
        [self showRightBarButtonItem];
    }
    
    - (void)showLeftBarButtonItem {
        if ([_webView canGoBack] || [_wk_WebView canGoBack]) {
            UIBarButtonItem *spaceItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
            spaceItem.width = -20;
            self.navigationItem.leftBarButtonItems = @[self.backBarButtonItem,spaceItem,self.closeBarButtonItem];
        } else {
            self.navigationItem.leftBarButtonItem = self.backBarButtonItem;
        }
    }
    
    - (void)showRightBarButtonItem {
        
    }
    
    #pragma mark 自定义导航按钮支持侧滑手势处理
    - (void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
        if (self.navigationController.viewControllers.count > 1) {
            self.delegate = self.navigationController.interactivePopGestureRecognizer.delegate;
            self.navigationController.interactivePopGestureRecognizer.delegate = self;
        }
    }
    
    - (void)viewWillDisappear:(BOOL)animated {
        [super viewWillDisappear:animated];
        self.navigationController.interactivePopGestureRecognizer.delegate = self.delegate;
    }
    
    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
        return self.navigationController.viewControllers.count > 1;
    }
    
    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
        return self.navigationController.viewControllers.count > 1;
    }
    
    #pragma mark getter
    - (UIBarButtonItem*)closeBarButtonItem {
        if (!_closeBarButtonItem) {
            _closeBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"关闭" style:UIBarButtonItemStylePlain target:self action:@selector(close:)];
        }
        return _closeBarButtonItem;
    }
    
    - (UIBarButtonItem*)backBarButtonItem {
        if (!_backBarButtonItem) {
            //        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
            //        [button setImage:[UIImage imageNamed:@"webview_back"] forState:UIControlStateNormal];
            _backBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"back"] style:UIBarButtonItemStylePlain target:self action:@selector(back:)];
        }
        return _backBarButtonItem;
    }
    
    - (UIWebView *)webView {
        if (!_webView) {
            _webView = [[UIWebView alloc]initWithFrame:CGRectMake(0, NAVI_HEIGHT + self.loadingProgressView.frame.size.height, self.view.bounds.size.width, self.view.bounds.size.height - NAVI_HEIGHT)];
            [_webView setScalesPageToFit:YES];
            _webView.delegate = self;
        }
        return _webView;
    }
    
    - (WKWebView*)wk_WebView {
        if (!_wk_WebView) {
            
            WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc]init];
            //设置偏好设置
            config.preferences = [[WKPreferences alloc]init];
            config.userContentController = [[WKUserContentController alloc]init];
            
            NSString *jSString = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";
            WKUserScript *wkUserScript = [[WKUserScript alloc] initWithSource:jSString injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
            [config.userContentController addUserScript:wkUserScript];
            config.allowsInlineMediaPlayback = YES;
            _wk_WebView = [[WKWebView alloc]initWithFrame:CGRectMake(0, NAVI_HEIGHT + self.loadingProgressView.frame.size.height, self.view.bounds.size.width, self.view.frame.size.height - NAVI_HEIGHT) configuration:config];
            _wk_WebView.navigationDelegate = self;
            _wk_WebView.UIDelegate = self;
            _wk_WebView.configuration.allowsInlineMediaPlayback = YES;
            _wk_WebView.configuration.requiresUserActionForMediaPlayback = NO;
            [_wk_WebView.scrollView setScrollEnabled:NO];
            //添加此属性可触发侧滑返回上一网页与下一网页操作
            _wk_WebView.allowsBackForwardNavigationGestures = YES;
            
            //下拉刷新
            if ([[[UIDevice currentDevice]systemVersion]floatValue] >= 10.0 && _canDownRefresh) {
                _wk_WebView.scrollView.refreshControl = self.refreshControl;
            }
            //进度监听
            [_wk_WebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:NULL];
        }
        return _wk_WebView;
    }
    
    - (UIProgressView *)loadingProgressView {
        if (!_loadingProgressView) {
            _loadingProgressView = [[UIProgressView alloc] initWithFrame:CGRectMake(0, NAVI_HEIGHT, self.view.frame.size.width, 5)];
            _loadingProgressView.progressTintColor = [UIColor greenColor];
        }
        return _loadingProgressView;
    }
    
    //刷新控件
    - (UIRefreshControl*)refreshControl {
        if (!_refreshControl) {
            _refreshControl = [[UIRefreshControl alloc]init];
            [_refreshControl addTarget:self action:@selector(webViewReload) forControlEvents:UIControlEventValueChanged];
        }
        return _refreshControl;
    }
    
    - (UIActivityIndicatorView *)indicatorView {
        if (!_indicatorView) {
            
            _indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
            _indicatorView.hidesWhenStopped = YES;
        }
        
        return _indicatorView;
    }
    
    - (UIButton*)reloadButton {
        if (!_reloadButton) {
            _reloadButton = [UIButton buttonWithType:UIButtonTypeCustom];
            _reloadButton.frame = CGRectMake(0, 0, 150, 150);
            _reloadButton.center = self.webView.center;
            _reloadButton.layer.cornerRadius = 75.0;
            [_reloadButton setBackgroundImage:[UIImage imageNamed:@"sure_placeholder_error"] forState:UIControlStateNormal];
            [_reloadButton setTitle:@"您的网络有问题,请检查您的网络设置" forState:UIControlStateNormal];
            [_reloadButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal];
            [_reloadButton setTitleEdgeInsets:UIEdgeInsetsMake(200, -50, 0, -50)];
            _reloadButton.titleLabel.numberOfLines = 0;
            _reloadButton.titleLabel.textAlignment = NSTextAlignmentCenter;
            CGRect rect = _reloadButton.frame;
            rect.origin.y -= 100;
            _reloadButton.frame = rect;
            //        _reloadButton.enabled = NO;
            _reloadButton.hidden = YES;
            [_reloadButton addTarget:self action:@selector(webViewReload) forControlEvents:UIControlEventTouchUpInside];
        }
        return _reloadButton;
    }
    
    @end
    
    
    • 利用webView加载html标签封装,并计算webView的内容高度
      .h
    #import <UIKit/UIKit.h>
    
    typedef void(^htmlWebViewDidLoadBlock)(CGFloat htmlHeight);
    
    @interface LCHtmlWebView : UIWebView<UIWebViewDelegate>
    
    
    @property (nonatomic, strong) NSMutableArray *imageViews;
    
    
    //添加html标签
    - (void)addHtmlPage:(NSString *)html;
    
    /**
     加载完成回调
     */
    @property (nonatomic, copy) htmlWebViewDidLoadBlock htmlDidLoadBlock;
    
    
    @end
    

    .m

    #import "LCHtmlWebView.h"
    #import "UIImageView+AFNetworking.h"//利用AFN下载图片
    
    @implementation LCHtmlWebView
    
    - (void)addHtmlPage:(NSString *)html {
        
        self.delegate = self;
        if (html.length == 0) {
            
            return;
        }
        NSRegularExpression *regx = [NSRegularExpression regularExpressionWithPattern:@"<img\\ssrc[^>]*/>" options:NSRegularExpressionAllowCommentsAndWhitespace error:nil];
        NSArray *result = [regx matchesInString:html options:NSMatchingReportCompletion range:NSMakeRange(0, html.length)];
        NSLog(@"result = %@",result);
        for (NSTextCheckingResult *item in result) {
            
            NSString *imgHtml = [html substringWithRange:[item rangeAtIndex:0]];
            NSArray *tmpArray = nil;
            if ([imgHtml rangeOfString:@"src=\""].location != NSNotFound) {
                
                tmpArray = [imgHtml componentsSeparatedByString:@"src=\""];
            }else if ([imgHtml rangeOfString:@"src"].location != NSNotFound) {
                
                tmpArray = [imgHtml componentsSeparatedByString:@"src="];
            }
            
            if (tmpArray.count >= 2) {
                
                NSString *src = tmpArray[1];
                NSUInteger loc = [src rangeOfString:@"\""].location;
                if (loc != NSNotFound) {
                    
                    src = [src substringFromIndex:loc];
                    NSLog(@"正确解析出来的src为:%@",src);
                    [self downloadImageWithUrl:src];
                }
            }
        }
        
        NSString *ht = @"<!DOCTYPE HTML><html><head><meta charset='utf-8'><meta name='viewport' content='width=device-width, initial-scale=1'></head><div style='font-size:100%;word-wrap: break-word;'><style>img{height:auto; width:auto/9; width:100%}</style>";
        
        NSString *h1 = @"</div></html>";
        NSString *htl = [NSString stringWithFormat:@"%@%@%@",ht, html,h1];
        
        [self loadHTMLString:htl baseURL:nil];
        
    
    }
    
    
    - (void)downloadImageWithUrl:(NSString *)src {
        
        // 注意:这里并没有写专门下载图片的代码,就直接使用了AFN的扩展,只是为了省麻烦而已。
        UIImageView *imgView = [[UIImageView alloc] init];
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:src]];
        [imgView setImageWithURLRequest:request placeholderImage:nil success:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, UIImage * _Nonnull image) {
            
        } failure:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSError * _Nonnull error) {
            NSLog(@"download image url fail: %@", src);
        }];
        
        if (self.imageViews == nil) {
            self.imageViews = [[NSMutableArray alloc] init];
        }
        [self.imageViews addObject:imgView];
    }
    
    
    - (void)webViewDidFinishLoad:(UIWebView *)webView {
        
        //计算标签的内容高度
        CGFloat height = [[self stringByEvaluatingJavaScriptFromString:@"document.body.offsetHeight"] floatValue];
        
        if (self.htmlDidLoadBlock) {
            self.htmlDidLoadBlock(height);
        }
        
    }
    

    相关文章

      网友评论

          本文标题:IOS WKWebView 和webView简单封装

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