IOS WKWebView 和webView简单封装
2018-02-07 本文已影响315人
MrLiangC
- 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);
}
}