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

//
// 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