You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
414 lines
16 KiB
414 lines
16 KiB
// |
|
// WebViewController.m |
|
// watch |
|
// |
|
// Created by xTT on 2017/9/3. |
|
// Copyright © 2017年 xTT. All rights reserved. |
|
// |
|
#import "WebViewController.h" |
|
#import <Photos/Photos.h> |
|
|
|
@interface WebViewController()<WKNavigationDelegate> |
|
|
|
|
|
|
|
/// 右侧的选项 容器View |
|
@property (nonatomic, strong) UIView *webOptionView; |
|
/// 进度条 |
|
@property (nonatomic, strong) UIProgressView* progressView; |
|
/// 当前链接 |
|
@property (nonatomic, strong) NSString* currentURLString; |
|
|
|
/// 第一次加载完成 |
|
@property (nonatomic, assign) BOOL isFristLoadFinish; |
|
/** |
|
隐藏导航栏时有的返回按钮 |
|
*/ |
|
@property (nonatomic, strong) UIButton *backBtn; |
|
|
|
@end |
|
@implementation WebViewController |
|
|
|
- (WKWebView *)myWebView{ |
|
if (!_myWebView) { |
|
_myWebView = [[WKWebView alloc] init]; |
|
[self.view addSubview:_myWebView]; |
|
[_myWebView mas_makeConstraints:^(MASConstraintMaker *make) { |
|
make.left.right.equalTo(self.view); |
|
make.top.equalTo(self.view).offset(iPhoneX_NavHeight); |
|
make.bottom.equalTo(self.view.mas_bottom); |
|
}]; |
|
} |
|
return _myWebView; |
|
} |
|
|
|
-(UIProgressView *)progressView{ |
|
if(!_progressView){ |
|
_progressView = [[UIProgressView alloc] init]; |
|
_progressView.progressTintColor = mainColor; |
|
[self.view addSubview:_progressView]; |
|
[_progressView mas_makeConstraints:^(MASConstraintMaker *make) { |
|
make.top.mas_offset(0); |
|
make.left.mas_offset(0); |
|
make.right.mas_offset(0); |
|
make.height.mas_offset(3); |
|
}]; |
|
} |
|
return _progressView; |
|
} |
|
|
|
|
|
-(BOOL)prefersStatusBarHidden{ |
|
if(self.isHiddenNavigationBar){ |
|
return YES; |
|
} |
|
return NO; |
|
} |
|
-(void)viewWillAppear:(BOOL)animated{ |
|
[super viewWillAppear:animated]; |
|
if(self.isHiddenNavigationBar){ |
|
[self.navigationController.navigationBar setHidden:YES]; |
|
} |
|
} |
|
//-(BOOL)prefersStatusBarHidden{ |
|
// if(self.isHiddenNavigationBar){ |
|
// return YES; |
|
// }else{ |
|
// return NO; |
|
// } |
|
//} |
|
|
|
//进入显示页面 |
|
-(void)viewDidAppear:(BOOL)animated{ |
|
[super viewDidAppear:animated]; |
|
if (self.isShowMoreOperations){ |
|
// 禁用返回手势 |
|
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) { |
|
self.navigationController.interactivePopGestureRecognizer.enabled = NO; |
|
} |
|
} |
|
} |
|
//退出页面 |
|
-(void)viewDidDisappear:(BOOL)animated{ |
|
[super viewDidDisappear:animated]; |
|
if(self.isHiddenNavigationBar){ |
|
[[UIApplication sharedApplication] setStatusBarHidden:NO]; |
|
[self.navigationController.navigationBar setHidden:NO]; |
|
} |
|
|
|
//移除观察者 |
|
@try { |
|
[_myWebView removeObserver:self forKeyPath:NSStringFromSelector(@selector(estimatedProgress))]; |
|
} @catch (NSException *exception) { |
|
NSLog(@"RemoveObserver estimatedProgress ERROR!"); |
|
} |
|
|
|
// [_webView removeObserver:self forKeyPath:NSStringFromSelector(@selector(title))]; |
|
if (self.isShowMoreOperations){ |
|
// 开启返回手势 |
|
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) { |
|
self.navigationController.interactivePopGestureRecognizer.enabled = YES; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
//kvo 监听进度 必须实现此方法 |
|
-(void)observeValueForKeyPath:(NSString *)keyPath |
|
ofObject:(id)object |
|
change:(NSDictionary<NSKeyValueChangeKey,id> *)change |
|
context:(void *)context{ |
|
if ([keyPath isEqualToString:NSStringFromSelector(@selector(estimatedProgress))] |
|
&& object == _myWebView) { |
|
NSLog(@"网页加载进度 = %f",_myWebView.estimatedProgress); |
|
self.progressView.progress = _myWebView.estimatedProgress; |
|
if (_myWebView.estimatedProgress >= 1.0f) { |
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ |
|
self.progressView.progress = 0; |
|
self.progressView.hidden = YES; |
|
}); |
|
}else{ |
|
self.progressView.hidden = NO; |
|
} |
|
} |
|
else if([keyPath isEqualToString:@"title"] |
|
&& object == _myWebView){ |
|
if (self.isShowMoreOperations) { |
|
|
|
} |
|
} |
|
else{ |
|
[super observeValueForKeyPath:keyPath |
|
ofObject:object |
|
change:change |
|
context:context]; |
|
} |
|
} |
|
|
|
- (void)viewDidLoad{ |
|
|
|
[super viewDidLoad]; |
|
|
|
if(self.isShowMoreOperations){ |
|
|
|
UIBarButtonItem *webOperationBtn = [[UIBarButtonItem alloc] initWithImage: [UIImage imageNamed:@"icon_operation"] style:UIBarButtonItemStylePlain target:self action:@selector(webOperationAction:)]; |
|
|
|
|
|
UIBarButtonItem *closeBtn = [[UIBarButtonItem alloc] initWithImage: [UIImage imageNamed:@"icon_close"] style:UIBarButtonItemStylePlain target:self action:@selector(closeWebAction:)]; |
|
//右键复制连接或者在浏览器打开 |
|
self.navigationItem.rightBarButtonItems = @[webOperationBtn,closeBtn]; |
|
} |
|
|
|
|
|
//添加监测网页加载进度的观察者 |
|
[self.myWebView addObserver:self |
|
forKeyPath:@"estimatedProgress" |
|
options:0 |
|
context:nil]; |
|
|
|
//添加监测网页标题title的观察者 |
|
[self.myWebView addObserver:self |
|
forKeyPath:@"title" |
|
options:NSKeyValueObservingOptionNew |
|
context:nil]; |
|
|
|
if(self.content){ |
|
[self.myWebView loadHTMLString:self.content baseURL:nil]; |
|
}else{ |
|
[self.myWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.url]]]; |
|
} |
|
self.myWebView.navigationDelegate = self; |
|
if(self.isHiddenNavigationBar){ |
|
//创建返回按钮 |
|
// _backBtn = [UIButton buttonWithType:UIButtonTypeSystem]; |
|
// _backBtn.frame = CGRectMake(14, 40, 30, 30); |
|
// [_backBtn setBackgroundImage:[UIImage imageNamed:@"icon_return_black"] forState:0]; |
|
// [_backBtn addTarget:self action:@selector(goBack:) forControlEvents:UIControlEventTouchUpInside]; |
|
// [self.view addSubview:_backBtn]; |
|
} |
|
|
|
|
|
|
|
} |
|
|
|
- (void)openScheme:(NSString *)scheme { |
|
UIApplication *application = [UIApplication sharedApplication]; |
|
NSURL *URL = [NSURL URLWithString:scheme]; |
|
|
|
//iOS 10 以后 |
|
if ([application respondsToSelector:@selector(openURL:options:completionHandler:)]) { |
|
//1 如果这个要打开的URL有效,并且在应用中配置它布尔值为true(YES)时才可以打开,否则打不开 |
|
// NSDictionary *options = @{UIApplicationOpenURLOptionUniversalLinksOnly : @YES}; |
|
//2 此时与openURL功能相似 |
|
NSDictionary *options =@{}; |
|
[application openURL:URL options:options |
|
completionHandler:^(BOOL success) { |
|
NSLog(@"Open %@: %d",scheme,success); |
|
}]; |
|
} else { |
|
if ([application canOpenURL:URL]) { |
|
BOOL success = [application openURL:URL]; |
|
NSLog(@"Open %@: %d",scheme,success); |
|
} |
|
|
|
} |
|
} |
|
|
|
-(void)goBack:(id)sender{ |
|
if(self.isShowMoreOperations){ |
|
if (self.myWebView.canGoBack) { |
|
[self.myWebView goBack]; |
|
}else{ |
|
[self.navigationController popViewControllerAnimated:YES]; |
|
} |
|
}else{ |
|
[super goBack:sender]; |
|
} |
|
|
|
} |
|
- (void)closeWebAction:(id)sender{ |
|
[self.navigationController popViewControllerAnimated:YES]; |
|
} |
|
- (void)webOperationAction:(UIBarButtonItem*)sender{ |
|
if(self.isFristLoadFinish == NO){ |
|
return; |
|
} |
|
//如果还没加载完成,不能打开 |
|
if(!_webOptionView){ |
|
CGFloat aWidth = 180; |
|
_webOptionView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, ScreenWidth, ScreenHeight)]; |
|
_webOptionView.backgroundColor = RGBA(2, 1, 6, 0.4); |
|
_webOptionView.userInteractionEnabled = YES; |
|
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hiddenWebOptionAction:)]; |
|
[_webOptionView addGestureRecognizer:tap]; |
|
UIWindow *win = [UIApplication sharedApplication].keyWindow; |
|
[win addSubview:_webOptionView]; |
|
UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(ScreenWidth-aWidth-25, getRectNavAndStatusHight - 20, aWidth, 90)]; |
|
contentView.layer.cornerRadius = 5; |
|
contentView.layer.masksToBounds = YES; |
|
|
|
contentView.backgroundColor = [UIColor whiteColor]; |
|
[_webOptionView addSubview:contentView]; |
|
UIButton *copBtn = [UIButton buttonWithType:UIButtonTypeCustom]; |
|
[copBtn setImage:[UIImage imageNamed:@"icon_copylink"] forState:0]; |
|
[copBtn setTitle:@"复制连接" forState:0]; |
|
copBtn.frame = CGRectMake(0, 0, aWidth, 45); |
|
copBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; |
|
[copBtn setTitleColor:RGB(52, 52, 52) forState:0]; |
|
copBtn.titleLabel.font = DefineFontSize; |
|
copBtn.imageEdgeInsets = UIEdgeInsetsMake(0, 15, 0, 0); |
|
copBtn.titleEdgeInsets =UIEdgeInsetsMake(0, 15+15, 0, 0); |
|
[contentView addSubview:copBtn]; |
|
[copBtn addTarget:self action:@selector(copyLinkAction:) forControlEvents:UIControlEventTouchUpInside]; |
|
|
|
UIButton *openWebBtn = [UIButton buttonWithType:UIButtonTypeCustom]; |
|
[openWebBtn setImage:[UIImage imageNamed:@"icon_browser_open"] forState:0]; |
|
[openWebBtn setTitleColor:RGB(52, 52, 52) forState:0]; |
|
[openWebBtn setTitle:@"在浏览器中打开" forState:0]; |
|
openWebBtn.titleLabel.font = DefineFontSize; |
|
openWebBtn.imageEdgeInsets = UIEdgeInsetsMake(0, 15, 0, 0); |
|
openWebBtn.titleEdgeInsets =UIEdgeInsetsMake(0, 15+15, 0, 0); |
|
openWebBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; |
|
openWebBtn.frame = CGRectMake(0, 45, aWidth, 45); |
|
[contentView addSubview:openWebBtn]; |
|
[openWebBtn addTarget:self action:@selector(openLinkWithSystemWeb:) forControlEvents:UIControlEventTouchUpInside]; |
|
|
|
|
|
} |
|
_webOptionView.hidden = !_webOptionView.hidden; |
|
|
|
} |
|
|
|
- (void)hiddenWebOptionAction:(id)sender{ |
|
if(_webOptionView){ |
|
_webOptionView.hidden = YES; |
|
} |
|
} |
|
|
|
/// 复制连接 |
|
- (void)copyLinkAction:(UIButton*)sender{ |
|
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; |
|
if(self.currentURLString.length > 0){ |
|
pasteboard.string = self.currentURLString; |
|
xLog(@"复制连接到剪贴板了...:%@",self.currentURLString); |
|
[SVProgressHUD showSuccessWithStatus:@"链接已经成功复制到剪贴板"]; |
|
[self hiddenWebOptionAction:nil]; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
/// 打开浏览器 |
|
- (void)openLinkWithSystemWeb:(UIButton*)sender{ |
|
|
|
if(_currentURLString.length > 0){ |
|
|
|
// IOS11 以下的 |
|
if([[[UIDevice currentDevice] systemVersion] doubleValue] < 10.0){ |
|
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:_currentURLString]]; |
|
}else{ |
|
// iOS 11 以上 |
|
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:_currentURLString] options:@{} completionHandler:^(BOOL success) { |
|
xLog(@"success: %d",success); |
|
}]; |
|
} |
|
} |
|
[self hiddenWebOptionAction:nil]; |
|
} |
|
// 页面开始加载时调用 |
|
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation { |
|
} |
|
// 页面加载失败时调用 |
|
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error { |
|
[self.progressView setProgress:0.0f animated:NO]; |
|
} |
|
// 当内容开始返回时调用 |
|
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation { |
|
} |
|
// 页面加载完成之后调用 |
|
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { |
|
// [self getCookie]; |
|
self.currentURLString = webView.URL.absoluteURL.absoluteString; |
|
self.isFristLoadFinish = YES; |
|
xLog(@"页面加载完成时的连接:%@",self.currentURLString); |
|
} |
|
//提交发生错误时调用 |
|
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error { |
|
[self.progressView setProgress:0.0f animated:NO]; |
|
} |
|
// 接收到服务器跳转请求即服务重定向时之后调用 |
|
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation { |
|
} |
|
// 根据WebView对于即将跳转的HTTP请求头信息和相关信息来决定是否跳转 |
|
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { |
|
|
|
NSString * urlStr = navigationAction.request.URL.absoluteString; |
|
|
|
xLog(@"发送跳转请求:%@",urlStr); |
|
NSString * toJumpURL = @""; |
|
if ([urlStr containsString:@"apps.apple.com"] || [urlStr containsString:@"itunes.apple.com"]) { |
|
toJumpURL = [urlStr stringByReplacingOccurrencesOfString:@"https:" withString:@"itms-apps:"]; |
|
|
|
}else if (![urlStr hasPrefix:@"https://"] && ![urlStr hasPrefix:@"http://"]){ |
|
// 不含 https:// 和 http:// 的都跳转 |
|
|
|
toJumpURL = urlStr; |
|
} |
|
if(toJumpURL.length > 0){ |
|
if([toJumpURL containsString:@"://"]){ |
|
xLog(@"只有包含 : < :// > 的才控制跳转浏览器: %@", urlStr); |
|
// IOS11 以下的 |
|
if([[[UIDevice currentDevice] systemVersion] doubleValue] < 11.0){ |
|
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:toJumpURL]]; |
|
}else{ |
|
// iOS 11 以上 |
|
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:toJumpURL] options:@{} completionHandler:^(BOOL success) { |
|
xLog(@"success: %d",success); |
|
}]; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
//自己定义的协议头 |
|
// NSString *htmlHeadString = @"github://"; |
|
// if([urlStr hasPrefix:htmlHeadString]){ |
|
// UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"通过截取URL调用OC" message:@"你想前往我的Github主页?" preferredStyle:UIAlertControllerStyleAlert]; |
|
// [alertController addAction:([UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { |
|
// }])]; |
|
// [alertController addAction:([UIAlertAction actionWithTitle:@"打开" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { |
|
// NSURL * url = [NSURL URLWithString:[urlStr stringByReplacingOccurrencesOfString:@"github://callName_?" withString:@""]]; |
|
// [[UIApplication sharedApplication] openURL:url]; |
|
// }])]; |
|
// [self presentViewController:alertController animated:YES completion:nil]; |
|
// decisionHandler(WKNavigationActionPolicyCancel); |
|
// }else{ |
|
decisionHandler(WKNavigationActionPolicyAllow); |
|
// } |
|
} |
|
|
|
// 根据客户端受到的服务器响应头以及response相关信息来决定是否可以跳转 |
|
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{ |
|
NSString * urlStr = navigationResponse.response.URL.absoluteString; |
|
NSLog(@"当前跳转地址:%@",urlStr); |
|
//允许跳转 |
|
decisionHandler(WKNavigationResponsePolicyAllow); |
|
//不允许跳转 |
|
//decisionHandler(WKNavigationResponsePolicyCancel); |
|
} |
|
//需要响应身份验证时调用 同样在block中需要传入用户身份凭证 |
|
//- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler{ |
|
// //用户身份信息 |
|
// NSURLCredential * newCred = [[NSURLCredential alloc] initWithUser:@"user123" password:@"123" persistence:NSURLCredentialPersistenceNone]; |
|
// //为 challenge 的发送方提供 credential |
|
// [challenge.sender useCredential:newCred forAuthenticationChallenge:challenge]; |
|
// completionHandler(NSURLSessionAuthChallengeUseCredential,newCred); |
|
//} |
|
//进程被终止时调用 |
|
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView{ |
|
} |
|
|
|
@end
|
|
|