IOS WKWebView 和webView简单封装

2018-02-07  本文已影响315人  MrLiangC
#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

#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);
    }
    
}
上一篇下一篇

猜你喜欢

热点阅读