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.
460 lines
18 KiB
460 lines
18 KiB
// |
|
// WebViewController.m |
|
// tongxin |
|
// |
|
// Created by weichao on 2019/03/01. |
|
// Copyright © 2019年 weichao. All rights reserved. |
|
// |
|
#import "ActivityWebViewController.h" |
|
#import <MapKit/MapKit.h> |
|
#import "Reachability.h" |
|
|
|
@interface ActivityWebViewController()<WKUIDelegate,WKNavigationDelegate,WKScriptMessageHandler,CLLocationManagerDelegate> |
|
|
|
|
|
{ |
|
CGRect WebFrame; |
|
BOOL _locationAuthorization; // 用户是否授权使用定位 |
|
BOOL _isDidLoadWeb; |
|
} |
|
/** |
|
隐藏导航栏时有的返回按钮 |
|
*/ |
|
@property (nonatomic, strong) UIButton *backBtn; |
|
@property (nonatomic, strong) UIProgressView *progressView; |
|
@property (strong,nonatomic) CLLocationManager* locationManager; |
|
@property (nonatomic, strong) NSString *cityName; |
|
@property (nonatomic, strong) UIView *tempView; |
|
|
|
@end |
|
@implementation ActivityWebViewController |
|
|
|
- (WKWebView *)myWebView{ |
|
if (!_myWebView) { |
|
//创建 WKWebView 配置对象 |
|
|
|
|
|
WKWebViewConfiguration *config = [WKWebViewConfiguration new]; |
|
// config.userContentController = wkUController; |
|
WKPreferences *preferences = [WKPreferences new]; |
|
preferences.javaScriptCanOpenWindowsAutomatically = YES; |
|
// preferences.minimumFontSize = 40.0; |
|
config.preferences = preferences; |
|
CGFloat tabBarHeight = self.tabBarController.tabBar.height; |
|
|
|
CGRect tempViewFrame; |
|
if(getRectNavAndStatusHight > 64){ |
|
//X |
|
if(self.isShowBack){ |
|
WebFrame = CGRectMake(0, getRectNavAndStatusHight-44, ScreenWidth, ScreenHeight-tabBarHeight-getRectNavAndStatusHight+44 ); |
|
tempViewFrame = CGRectMake(0, 0, ScreenWidth, getRectNavAndStatusHight-44); |
|
}else{ |
|
CGFloat WebNacv = 55; //网页的导航栏高度 |
|
WebFrame = CGRectMake(0, getRectNavAndStatusHight-WebNacv, ScreenWidth, ScreenHeight-tabBarHeight-getRectNavAndStatusHight+WebNacv ); |
|
tempViewFrame = CGRectMake(0, 0, ScreenWidth, getRectNavAndStatusHight-WebNacv); |
|
} |
|
}else{ |
|
if(self.isShowBack){ |
|
WebFrame = CGRectMake(0, 0, ScreenWidth, ScreenHeight-tabBarHeight); |
|
tempViewFrame = CGRectMake(0, 0, ScreenWidth, 0); |
|
}else{ |
|
//不显示返回按钮的是首页 |
|
WebFrame = CGRectMake(0, 20, ScreenWidth, ScreenHeight-tabBarHeight-20); |
|
tempViewFrame = CGRectMake(0, 0, ScreenWidth, 20); |
|
|
|
} |
|
} |
|
|
|
_tempView = [[UIView alloc] initWithFrame:tempViewFrame]; |
|
_tempView.backgroundColor = mainColor; |
|
[self.view addSubview:_tempView]; |
|
_tempView.hidden = YES; |
|
_myWebView = [[WKWebView alloc] initWithFrame:WebFrame configuration:config]; |
|
if (@available(iOS 11.0, *)) { |
|
_myWebView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; |
|
} else { |
|
self.edgesForExtendedLayout = UIRectEdgeNone; |
|
} |
|
|
|
[self.view addSubview:_myWebView]; |
|
} |
|
return _myWebView; |
|
} |
|
|
|
-(void)viewWillAppear:(BOOL)animated{ |
|
[super viewWillAppear:animated]; |
|
//隐藏导航栏 |
|
// [[UIApplication sharedApplication] setStatusBarHidden:YES]; |
|
[self.navigationController.navigationBar setHidden:YES]; |
|
|
|
// addScriptMessageHandler 很容易导致循环引用 |
|
// 控制器 强引用了WKWebView,WKWebView copy(强引用了)configuration, configuration copy (强引用了)userContentController |
|
// userContentController 强引用了 self (控制器) |
|
|
|
[self.myWebView.configuration.userContentController addScriptMessageHandler:self name:@"Location"]; |
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loadURL) name:NoReachableRefreshNotification object:nil]; |
|
if(![self.url containsString:ActivityURLStr]){ |
|
xLog(@"不是首页:%@",self.url); |
|
[self setHiddenTabBottomBar:YES]; |
|
}else{ |
|
xLog(@"是首页:%@",self.url); |
|
[self setHiddenTabBottomBar:NO]; |
|
} |
|
} |
|
-(void)viewWillDisappear:(BOOL)animated{ |
|
[super viewWillDisappear:animated]; |
|
|
|
// 因此这里要记得移除handlers |
|
[self.myWebView.configuration.userContentController removeScriptMessageHandlerForName:@"Location"]; |
|
|
|
} |
|
-(void)viewDidDisappear:(BOOL)animated{ |
|
self.tabBarController.tabBar.hidden = NO; |
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:NoReachableRefreshNotification object:nil]; |
|
} |
|
|
|
//-(BOOL)prefersStatusBarHidden{ |
|
// if(self.isHiddenNavigationBar){ |
|
// return YES; |
|
// }else{ |
|
// return NO; |
|
// } |
|
//} |
|
|
|
- (void)viewDidLoad{ |
|
self.view.backgroundColor = [UIColor whiteColor]; |
|
self.isSetTranslucent = NO; |
|
[super viewDidLoad]; |
|
if(!self.url){ |
|
self.url = ActivityURLStr; |
|
[SVProgressHUD show]; |
|
} |
|
[self loadURL]; |
|
WEAKSELF |
|
self.myWebView.UIDelegate = self; |
|
self.myWebView.navigationDelegate = self; |
|
self.myWebView.scrollView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ |
|
[weakSelf loadURL]; |
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ |
|
[weakSelf.myWebView.scrollView.mj_header endRefreshing]; |
|
}); |
|
}]; |
|
|
|
if(self.isShowBack){ |
|
UIButton *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]; |
|
} |
|
|
|
|
|
[self initProgressView]; |
|
[self initNotReachable]; |
|
[self startLocation]; |
|
// [self.myWebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil]; |
|
// if(self.isHiddenNavigationBar){ |
|
// //创建返回按钮 |
|
// _backBtn = [UIButton buttonWithType:UIButtonTypeSystem]; |
|
// _backBtn.frame = CGRectMake(5, 26, 30, 30); |
|
// [_backBtn setBackgroundImage:[UIImage imageNamed:@"icon_return_round"] forState:0]; |
|
// [_backBtn addTarget:self action:@selector(goBack:) forControlEvents:UIControlEventTouchUpInside]; |
|
// [self.view addSubview:_backBtn]; |
|
// } |
|
} |
|
- (void)loadURL{ |
|
[self.myWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.url]]]; |
|
if(!self.cityName && _locationAuthorization){ |
|
[self startLocation]; |
|
} |
|
} |
|
|
|
- (void)initNotReachable{ |
|
[self.view addSubview:self.noDataSourceImageView]; |
|
[self.view addSubview:self.noReachableImageView]; |
|
[self.view addSubview:self.noDataSourcelabel]; |
|
[self.noDataSourceImageView mas_makeConstraints:^(MASConstraintMaker *make) { |
|
make.center.equalTo(self.myWebView); |
|
}]; |
|
|
|
[self.noReachableImageView mas_makeConstraints:^(MASConstraintMaker *make) { |
|
make.center.equalTo(self.myWebView); |
|
}]; |
|
} |
|
- (void)initProgressView |
|
{ |
|
CGFloat kScreenWidth = [[UIScreen mainScreen] bounds].size.width; |
|
UIProgressView *progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 2)]; |
|
progressView.tintColor = [UIColor redColor]; |
|
progressView.trackTintColor = [UIColor lightGrayColor]; |
|
[self.view addSubview:progressView]; |
|
self.progressView = progressView; |
|
} |
|
|
|
//开始定位 |
|
|
|
-(void)startLocation{ |
|
if(!self.locationManager){ |
|
self.locationManager = [[CLLocationManager alloc] init]; |
|
self.locationManager.delegate = self; |
|
self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer; |
|
// 位置变更距离 |
|
self.locationManager.distanceFilter = 1000.0f; |
|
if ([CurrentSystemVersion doubleValue] > 8.0){ |
|
if([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined){ |
|
[self.locationManager requestWhenInUseAuthorization]; |
|
} |
|
} |
|
// if ([CurrentSystemVersion doubleValue] >= 8.0) { |
|
// _locationManager.allowsBackgroundLocationUpdates =YES; |
|
// } |
|
// [self locationManager:self.locationManager didChangeAuthorizationStatus:[CLLocationManager authorizationStatus]]; |
|
} |
|
[self.locationManager startUpdatingLocation]; |
|
} |
|
|
|
//MARK: 协议 CLLocationManagerDelegate |
|
|
|
/** |
|
权限改变 |
|
*/ |
|
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{ |
|
switch (status) { |
|
case kCLAuthorizationStatusNotDetermined: |
|
if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]){ |
|
[self.locationManager requestWhenInUseAuthorization]; |
|
} |
|
break; |
|
case kCLAuthorizationStatusDenied: |
|
xLog(@"用户拒绝获取定位位置"); |
|
_locationAuthorization = NO; |
|
break; |
|
case kCLAuthorizationStatusAuthorizedAlways: |
|
case kCLAuthorizationStatusAuthorizedWhenInUse: |
|
xLog(@"用户同意获取定位位置"); |
|
if(!self.cityName){ |
|
[self.locationManager startUpdatingLocation]; |
|
} |
|
|
|
break; |
|
default: |
|
break; |
|
} |
|
} |
|
|
|
/** |
|
位置更新 |
|
*/ |
|
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{ |
|
//此处locations存储了持续更新的位置坐标值,取最后一个值为最新位置,如果不想让其持续更新位置,则在此方法中获取到一个值之后让locationManager stopUpdatingLocation |
|
CLLocation *currentLocation = [locations lastObject]; |
|
// 获取当前所在的城市名 |
|
CLGeocoder *geocoder = [[CLGeocoder alloc] init]; |
|
//根据经纬度反向地理编译出地址信息 |
|
WEAKSELF |
|
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) { |
|
if (placemarks.count > 0){ |
|
CLPlacemark *placemark = [placemarks objectAtIndex:0]; |
|
//将获得的所有信息显示到label上 |
|
NSLog(@"%@",placemark.name); |
|
//获取城市 |
|
NSString *city = placemark.locality; |
|
self.cityName = city; |
|
if (!city) { |
|
//四大直辖市的城市信息无法通过locality获得,只能通过获取省份的方法来获得(如果city为空,则可知为直辖市) |
|
city = placemark.administrativeArea; |
|
weakSelf.cityName = city; |
|
//如果这个时候网页已经加载完成了,那就 重新加载一次 |
|
if(_isDidLoadWeb){ |
|
[weakSelf loadURL]; |
|
} |
|
}else if (error == nil && [placemarks count] == 0){ |
|
NSLog(@"No results were returned."); |
|
}else if (error != nil){ |
|
NSLog(@"An error occurred = %@", error); |
|
} |
|
} |
|
}]; |
|
|
|
//系统会一直更新数据,直到选择停止更新,因为我们只需要获得一次经纬度即可,所以获取之后就停止更新 |
|
[manager stopUpdatingLocation]; |
|
} |
|
|
|
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { |
|
if (error.code == kCLErrorDenied) { |
|
// 提示用户出错原因,可按住Option键点击 KCLErrorDenied的查看更多出错信息,可打印error.code值查找原因所在 |
|
} |
|
} |
|
|
|
|
|
- (void)dealloc |
|
{ |
|
NSLog(@"%s",__FUNCTION__); |
|
self.myWebView.UIDelegate = nil; |
|
self.myWebView.navigationDelegate = nil; |
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:NoReachableRefreshNotification object:nil]; |
|
// [self.myWebView removeObserver:self forKeyPath:@"estimatedProgress"]; |
|
} |
|
#pragma mark - private method |
|
- (void)getLocation |
|
{ |
|
if(!_locationAuthorization){ |
|
return; |
|
} |
|
// 获取位置信息 |
|
if(self.cityName){ |
|
// MARK: 原生 调用 JS |
|
NSString *city = [self.cityName stringByReplacingOccurrencesOfString:@"市" withString:@""]; |
|
NSString *jsStr = [NSString stringWithFormat:@"setLocation('%@')",city]; |
|
[self.myWebView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) { |
|
NSLog(@"%@----%@",result, error); |
|
}]; |
|
}else{ |
|
//如果定位还未成功那就2秒之后再调用一次 |
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ |
|
[self getLocation]; |
|
}); |
|
} |
|
|
|
|
|
} |
|
|
|
#pragma mark - KVO |
|
// 计算wkWebView进度条 |
|
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { |
|
if (object == self.myWebView && [keyPath isEqualToString:@"estimatedProgress"]) { |
|
CGFloat newprogress = [[change objectForKey:NSKeyValueChangeNewKey] doubleValue]; |
|
if (newprogress == 1) { |
|
[self.progressView setProgress:1.0 animated:YES]; |
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.7 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ |
|
self.progressView.hidden = YES; |
|
[self.progressView setProgress:0 animated:NO]; |
|
}); |
|
|
|
}else { |
|
self.progressView.hidden = NO; |
|
[self.progressView setProgress:newprogress animated:YES]; |
|
} |
|
} |
|
} |
|
|
|
#pragma mark - WKUIDelegate |
|
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler |
|
{ |
|
|
|
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提醒" message:message preferredStyle:UIAlertControllerStyleAlert]; |
|
[alert addAction:[UIAlertAction actionWithTitle:@"知道了" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { |
|
completionHandler(); |
|
}]]; |
|
|
|
[self presentViewController:alert animated:YES completion:nil]; |
|
} |
|
//MARK: 协议 WKNavigationDelegate |
|
|
|
/** |
|
MARK: 页面加载完成之后调用 |
|
*/ |
|
-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{ |
|
_isDidLoadWeb = YES; |
|
Reachability *reach = [Reachability reachabilityForInternetConnection]; |
|
[SVProgressHUD dismiss]; |
|
if([reach currentReachabilityStatus] == NotReachable){ |
|
xLog(@"无网络"); |
|
_tempView.hidden = YES; |
|
self.myWebView.hidden = YES; |
|
[self showNoReachableView]; |
|
[SVProgressHUD showErrorWithStatus:NSLocalizedStringFromTable(@"请检查您的网络设置", @"Localization", @"")]; |
|
[SVProgressHUD dismissWithDelay:1]; |
|
}else{ |
|
xLog(@"有网络"); |
|
[self hiddenNoReachableView]; |
|
_tempView.hidden = NO; |
|
|
|
self.myWebView.hidden = NO; |
|
} |
|
} |
|
|
|
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{ |
|
//如果是跳转一个新页面 |
|
if (navigationAction.targetFrame == nil) { |
|
WEAKSELF |
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ |
|
ActivityWebViewController* vc = [ActivityWebViewController new]; |
|
vc.url = navigationAction.request.URL.absoluteString; |
|
vc.isShowBack = YES; |
|
vc.hidesBottomBarWhenPushed = YES; |
|
[weakSelf.navigationController pushViewController:vc animated:YES]; |
|
}); |
|
decisionHandler(WKNavigationActionPolicyCancel); |
|
return; |
|
} |
|
self.url = navigationAction.request.URL.absoluteString; |
|
if(![self.url containsString:ActivityURLStr]){ |
|
xLog(@"不是首页:%@",self.url); |
|
[self setHiddenTabBottomBar:YES]; |
|
}else{ |
|
xLog(@"是首页:%@",self.url); |
|
[self setHiddenTabBottomBar:NO]; |
|
} |
|
decisionHandler(WKNavigationActionPolicyAllow); |
|
|
|
|
|
} |
|
|
|
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error{ |
|
xLog(@"didFailNavigation error:%@",error.description); |
|
} |
|
|
|
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error{ |
|
xLog(@"didFailProvisionalNavigation error:%@",error.description); |
|
[self webView:webView didFinishNavigation:navigation]; |
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
隐藏或者显示 TabBottomBar |
|
*/ |
|
-(void)setHiddenTabBottomBar:(BOOL)hidden{ |
|
self.tabBarController.tabBar.hidden = hidden; |
|
|
|
if(hidden){ |
|
//隐藏 |
|
self.myWebView.height = WebFrame.size.height+self.tabBarController.tabBar.height; |
|
}else{ |
|
//显示 |
|
self.myWebView.frame = WebFrame; |
|
} |
|
} |
|
|
|
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { |
|
scrollView.decelerationRate = UIScrollViewDecelerationRateNormal; |
|
} |
|
#pragma mark - WKScriptMessageHandler JS调用 原生会调用这里 |
|
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message |
|
{ |
|
// message.body -- Allowed types are NSNumber, NSString, NSDate, NSArray,NSDictionary, and NSNull. |
|
NSLog(@"body:%@",message.body); |
|
if ([message.name isEqualToString:@"Location"]) { |
|
[self getLocation]; |
|
} |
|
// else if ([message.name isEqualToString:@"Share"]) { |
|
// [self shareWithParams:message.body]; |
|
// } else if ([message.name isEqualToString:@"Color"]) { |
|
// [self changeBGColor:message.body]; |
|
// } else if ([message.name isEqualToString:@"Pay"]) { |
|
// [self payWithParams:message.body]; |
|
// } else if ([message.name isEqualToString:@"Shake"]) { |
|
// [self shakeAction]; |
|
// } else if ([message.name isEqualToString:@"GoBack"]) { |
|
// [self goBack]; |
|
// } else if ([message.name isEqualToString:@"PlaySound"]) { |
|
// [self playSound:message.body]; |
|
// } |
|
} |
|
|
|
@end
|
|
|