万能的wkWebview,哈哈

2019-02-26  本文已影响0人  艾希_可可

#import "KINWebBrowserViewController.h"
#import <MJRefresh/MJRefresh.h>
#import <JavaScriptCore/JavaScriptCore.h>
#import "LNBrowserPluginManager.h"
#import "NSString+LNUrl.h"
#import "AiWKProcessPool.h"

static void *KINWebBrowserContext = &KINWebBrowserContext;
@interface KINWebBrowserViewController ()

@property (nonatomic, strong) UIBarButtonItem* closeButtonItem;//关闭按钮
@property (nonatomic, strong) NSTimer *fakeProgressTimer;
@property (nonatomic, strong) NSURL *URLToLaunchWithPermission;
@property (nonatomic, strong) UIAlertController *externalAppPermissionAlertView;
// js和native交互的管理器
@property (nonatomic, strong) LNBrowserPluginManager *pluginManager;
@end

@implementation KINWebBrowserViewController
#pragma mark - Static Initializers

+ (KINWebBrowserViewController *)webBrowser {
    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
    KINWebBrowserViewController *webBrowserViewController = [[self alloc] initWithConfiguration:configuration];
    return webBrowserViewController;
}
#pragma mark - Initializers初始化生命周期
- (id)init {
    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
    return [self initWithConfiguration:configuration];
}
- (id)initWithConfiguration:(WKWebViewConfiguration *)configuration {
    self = [super init];
    if(self) {
        MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingTarget:self.wkWebView refreshingAction:@selector(reload)];
        header.lastUpdatedTimeLabel.hidden = YES;
        self.showsURLInNavigationBar = NO;
        self.showsPageTitleInNavigationBar = YES;
        [self.view addSubview:self.wkWebView];
        [self updateWebViewCookie];
    }
    return self;
}
#pragma mark - 导航设置---------生命周期
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self updateNavigationBarState];
    if ([self.wkWebView.URL.absoluteString containsString:@"progresslist"] && [self.wkWebView.title isEqualToString:@"申请额度"]) {
        [self refreshWKwebView];
    }
    if ([self.wkWebView.title isEqualToString:@"集市"]) {
        [self.navigationController setNavigationBarHidden:YES animated:false];
        [self.view addSubview:self.progressBar];
        self.progressBar.frame = CGRectMake(0, kStatusBarHeight, __kScreenWidth, 2);
        [self.wkWebView setFrame:CGRectMake(0, kStatusBarHeight, __kScreenWidth, __kScreenHeight-kTabBarHeight-kStatusBarHeight)];//-88
    }else{
        [self.navigationController setNavigationBarHidden:NO animated:false];
        [self.navigationController.navigationBar addSubview:self.progressBar];
        self.progressBar.frame = CGRectMake(0, 0, __kScreenWidth, 2);
        if ([self.wkWebView.title isEqualToString:@"基本信息"] || [self.wkWebView.title isEqualToString:@"银行卡绑定"] || [self.wkWebView.title isEqualToString:@"贷款相关协议"]) {
            [self.wkWebView setFrame:CGRectMake(0, 0, __kScreenWidth, __kScreenHeight-kTopHeight)];
        }else{
            [self.wkWebView setFrame:CGRectMake(0, 0, __kScreenWidth, __kScreenHeight-kTabBarHeight-kTopHeight)];
        }
    }
}
-(void)viewDidAppear:(BOOL)animated{

}
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self.progressBar removeFromSuperview];
}
-(void)viewDidDisappear:(BOOL)animated{
    [super viewDidDisappear:animated];
//    [self deleteWebCache];
//    [self cleanCacheAndCookie];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 初始化交互管理器
    _pluginManager = [[LNBrowserPluginManager alloc] initWithBrowser:self];
    [_pluginManager addDefaultPlugins];
    //更新webView的cookie
    [self updateWebViewCookie];
    self.progressBar = [[UNProgressBar alloc] init];
    [self.progressBar setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin];
//    [self addSpaceButton];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshWKwebView) name:@"refreshWKwebView" object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(backMorenHomeResultPage) name:@"backMorenHomeResultPage" object:nil];

}
//回到首页页面
-(void)backMorenHomeResultPage{
    
    [self.wkWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@sudaihomepage",kDomainLSDKUrl]]]];
}
-(void)refreshWKwebView{
    YEAFNAppLog(@"刷新的时候链接%@",self.webURLString);
    [self.wkWebView reload];
}
-(WKWebView *)wkWebView{
    if (!_wkWebView){
        WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
        WKUserContentController *userContentController = [[WKUserContentController alloc] init];

        // 注入获取app版本号的js代码
        WKUserScript *script = [[WKUserScript alloc] initWithSource:[self getVersionInjectionCode] injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
        [userContentController addUserScript:script];
        // 执行js,初始化时添加cookies
        WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource:[self cookieString] injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
        //添加Cookie
        [userContentController addUserScript:cookieScript];
        //页面加载完成立刻回调,获取页面上的所有Cookie
        WKUserScript *cookieScript2 = [[WKUserScript alloc] initWithSource:@"                window.webkit.messageHandlers.currentCookies.postMessage(document.cookie);" injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:NO];
        [userContentController addUserScript:cookieScript2];
        configuration.userContentController = userContentController;
        
        configuration.processPool = [AiWKProcessPool singleWkProcessPool];
        WKPreferences *preferences = [[WKPreferences alloc]init];
        preferences.javaScriptCanOpenWindowsAutomatically = YES;
        configuration.preferences = preferences;
        
        _wkWebView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
//        self.webView.allowsBackForwardNavigationGestures = YES; //允许右滑返回上个链接,左滑前进
        _wkWebView.allowsLinkPreview = YES; //允许链接3D Touch
        [_wkWebView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
        [_wkWebView setNavigationDelegate:self];
        [_wkWebView setUIDelegate:self];
        [_wkWebView setMultipleTouchEnabled:YES];
        [_wkWebView setAutoresizesSubviews:YES];
        [_wkWebView.scrollView setAlwaysBounceVertical:YES];
        _wkWebView.scrollView.delegate = self;
//        _wkWebView.scrollView.contentInset = UIEdgeInsetsMake(-200, 0, 0, 0);
        _wkWebView.backgroundColor = [UIColor clearColor];
        [_wkWebView addObserver:self forKeyPath:NSStringFromSelector(@selector(estimatedProgress)) options:0 context:KINWebBrowserContext];
    }
    return _wkWebView;
}
#pragma mark - scrollView代理
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
    scrollView.decelerationRate = UIScrollViewDecelerationRateNormal;
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
    [self.wkWebView setNeedsLayout];
}
-(void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context{
    YEAFNAppLog(@"什么东东observer==%@,keyPath====%@,context=====%@",observer,keyPath,context);
}
#pragma mark - 导航设置
- (void)addleftBackItem{
    if (self.navigationController) {
        self.navigationController.interactivePopGestureRecognizer.enabled = YES;
        self.navigationItem.leftBarButtonItems = nil;
        if ([self.navigationController.viewControllers indexOfObject:self] > 0) {
            self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:kNavBtn_left_custom] style:UIBarButtonItemStylePlain target:self action:@selector(goBackLastPage:)];

        }
    }
}
- (void)checkWebViewCanGoBack{
        if ([self.wkWebView canGoBack]) {
            [self addSpaceButton];
        }
}
#pragma mark - NavigationItem
- (void)goBackLastPage:(UIButton *)sender {
    if ([self.wkWebView canGoBack]) {//判断是否可以返回,如果可以返回添加X按钮
        [self.wkWebView goBack];
        
//        if (LSTabBarViewController.instance.selectedIndex == 0 || LSTabBarViewController.instance.selectedIndex == 1) {
        if ([self.wkWebView.URL.absoluteString containsString:@"hardwaremall"] || [self.wkWebView.URL.absoluteString containsString:@"integration"]) {
            [self.wkWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@",self.wkWebView.URL.absoluteString]]]];
        }

        
        [self addSpaceButton];
    }

//    if ([self gotoBack]) {
//        [self closeItemClicked];
//    }else{
//
//    }
}
- (BOOL)gotoBack{
        if ([self.wkWebView canGoBack]) {//判断是否可以返回,如果可以返回添加X按钮
                [self.wkWebView goBack];
                [self addSpaceButton];
            return NO;
        }
    return YES;
}
- (void)addSpaceButton{
    if ([self.wkWebView.title isEqualToString:@"商城"] || [self.wkWebView.title isEqualToString:@"我的"] || [self.wkWebView.title isEqualToString:@"活动"] || [self.wkWebView.title isEqualToString:@"积分"] || [self.wkWebView.title isEqualToString:@"集市"] || [self.wkWebView.title isEqualToString:@"首页"] || [self.wkWebView.title isEqualToString:@"信用"] || [self.wkWebView.title isEqualToString:@"达客良品"] || ([self.wkWebView.URL.absoluteString containsString:@"hardwaremall"] && [self.wkWebView.title isEqualToString:@"达客良品"]) || ([self.wkWebView.URL.absoluteString containsString:@"integration"] && [self.wkWebView.title isEqualToString:@"信用"]) || ([self.wkWebView.URL.absoluteString containsString:@"homePage"] && [self.wkWebView.title isEqualToString:@"积分"]) || ([self.wkWebView.URL.absoluteString containsString:@"minePage"] && [self.wkWebView.title isEqualToString:@"我的"]) || [self.wkWebView.title isEqualToString:@"达客速贷-还款"] || [self.webURLString containsString:@"hardwaremall"] || [self.webURLString containsString:@"integration"] || [self.webURLString containsString:@"minePage"] || [self.webURLString containsString:@"homePage"]){// || [self.wkWebView.URL.absoluteString containsString:@"hardwaremall"]
        self.navigationItem.leftBarButtonItem = nil;
        self.navigationItem.leftBarButtonItems = @[];
    }else{
        self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:kNavBtn_left_custom] style:UIBarButtonItemStylePlain target:self action:@selector(goBackLastPage:)];
    }
}
-(UIBarButtonItem*)closeButtonItem{
    if (!_closeButtonItem) {
        _closeButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"nav_icon_close"] style:UIBarButtonItemStylePlain target:self action:@selector(closeItemClicked)];
    }
    return _closeButtonItem;
}
-(void)closeItemClicked{
    
    if (_isgoRoot) {
        [self.navigationController popToRootViewControllerAnimated:true];
    }else{
        [self.navigationController popViewControllerAnimated:YES];
    }
}
#pragma mark - NavigationBar State
- (void)updateNavigationBarState {
    if(self.wkWebView.loading) {
        if(self.showsURLInNavigationBar) {
            NSString *URLString;
            if(self.wkWebView) {
                URLString = [self.wkWebView.URL absoluteString];
            }
            URLString = [URLString stringByReplacingOccurrencesOfString:@"http://" withString:@""];
            URLString = [URLString stringByReplacingOccurrencesOfString:@"https://" withString:@""];
            URLString = [URLString substringToIndex:[URLString length]-1];
            if (self.navigationItem.title == nil) {
                self.navigationItem.title = URLString;
            }
        }
    } else {
        if(self.showsPageTitleInNavigationBar) {
            if(self.wkWebView) {
                self.navigationItem.title = self.wkWebView.title;
            }
        }
    }
    if (self.isHomeView && [self gotoBack]) {
        if (self.delegate && [self.delegate respondsToSelector:@selector(showLeftBackItem)]) {
            [self.delegate showLeftBackItem];
        }
    }
    self.tintColor = self.tintColor;
    self.barTintColor = self.barTintColor;
}

#pragma mark - Public 加载方式
- (void)loadRequest:(NSURLRequest *)request {
    if(self.wkWebView) {
        [self.wkWebView loadRequest:request];
    }
}
- (void)loadUrl:(NSString *)url
{
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
    //给发出的request也添加上cookies
    [self.wkWebView loadRequest:[self fixRequest:request]];
}
- (void)loadURLString:(NSString *)URLString {
    YEAFNAppLog(@"*******************加载的链接%@",URLString);
    self.webURLString = URLString;
    NSURL *URL = [NSURL URLWithString:URLString];
    NSString *urlString = URL.absoluteString;
    //给发出的request也添加上cookies
//    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
//    [self.wkWebView loadRequest:[self fixRequest:request]];
    [self.wkWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]]];
}
- (void)loadHTMLString:(NSString *)HTMLString {
    if(self.wkWebView) {
        [self.wkWebView loadHTMLString:HTMLString baseURL:nil];
    }
}
#pragma mark----***一、WKWebView加载时序:
#pragma mark - WKNavigationDelegate********************
//1、开始请求,是否允许跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    YEAFNAppLog(@"1");
    YEAFNAppLog(@"开始请求,判断链接是否允许跳转------%@----%@",webView.title,self.wkWebView.URL.absoluteString);
    [self updateWebViewCookie];
    [self addSpaceButton];

    if(webView == self.wkWebView) {
        self.navigationItem.title = self.wkWebView.title;
        //判断导航
        if ([self.wkWebView.title isEqualToString:@"集市"]) {
            [self.navigationController setNavigationBarHidden:YES animated:false];
            [self.wkWebView setFrame:CGRectMake(0, kStatusBarHeight, __kScreenWidth, __kScreenHeight-kTabBarHeight-kStatusBarHeight)];//-88
        }else{
            [self.navigationController setNavigationBarHidden:NO animated:false];
            if ([self.wkWebView.title isEqualToString:@"基本信息"] || [self.wkWebView.title isEqualToString:@"银行卡绑定"] || [self.wkWebView.title isEqualToString:@"贷款相关协议"]) {
                [self.wkWebView setFrame:CGRectMake(0, 0, __kScreenWidth, __kScreenHeight-kTopHeight)];
            }else{
                [self.wkWebView setFrame:CGRectMake(0, 0, __kScreenWidth, __kScreenHeight-kTabBarHeight-kTopHeight)];
            }

        }
//        NSURL *URL = navigationAction.request.URL;
//        if(![self externalAppRequiredToOpenURL:URL]) {
//            if(!navigationAction.targetFrame) {
//                decisionHandler(WKNavigationActionPolicyCancel);
//                return;
//            }
//        }else if([[UIApplication sharedApplication] canOpenURL:URL]) {
////            [self launchExternalAppWithURL:URL];
//            decisionHandler(WKNavigationActionPolicyCancel);
//            return;
//        }
    }
    //解决Cookie丢失问题
//    NSURLRequest *originalRequest = navigationAction.request;
//    [self fixRequest:originalRequest];
    
    NSString *url = navigationAction.request.URL.absoluteString;
    
    if ([url hasPrefix:@"alipays://"] || [url hasPrefix:@"alipay://"]) {
        [[UIApplication sharedApplication]openURL:navigationAction.request.URL];
//                decisionHandler(WKNavigationActionPolicyAllow);
//                return;
    }
    if ([url containsString:@"itunes.apple.com"]) {
        [[UIApplication sharedApplication]openURL:navigationAction.request.URL];
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    UIApplication *app = [UIApplication sharedApplication];
    if ([url containsString:@"itms-services://"]) {
        [app openURL:[NSURL URLWithString:url] options:@{} completionHandler:^(BOOL success) {
            YEAFNAppLog(@"打开链接");
        }];
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    NSURL *URL = navigationAction.request.URL;
    NSString *scheme = [URL scheme];
    if ([scheme isEqualToString:@"tel"]) {
        NSString *resourceSpecifier = [URL resourceSpecifier];
        NSString *callPhone = [NSString stringWithFormat:@"telprompt://%@", resourceSpecifier];
        
        /// 防止iOS 10及其之后,拨打电话系统弹出框延迟出现
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:callPhone]];
        });
    }


    //允许跳转
    decisionHandler(WKNavigationActionPolicyAllow);//是否继续打开allow是,cancel否
    return;
}
//2、开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
    [self addSpaceButton];
    YEAFNAppLog(@"2开始加载时调用");
    if(webView == self.wkWebView) {
        //展期 点击确定按钮返回
        if ([[[webView URL] scheme] isEqualToString:@"pcrequest"]) {
            [self.navigationController popViewControllerAnimated:YES];
            return ;
        }
        if ([[[webView URL]scheme] isEqualToString:@"goShareView"]) {
            NSString * sharInfo;
            if (self.delegate && [self.delegate respondsToSelector:@selector(webBrowserClickShowShareView:)]) {
                [self.delegate webBrowserClickShowShareView:sharInfo];
            }
            [self.navigationController popViewControllerAnimated:NO];
            return ;
        }
        [self updateNavigationBarState];
        self.progressBar.isLoading = YES;
        [self.progressBar progressUpdate:.05];
        if([self.delegate respondsToSelector:@selector(webBrowser:didStartLoadingURL:)]) {
            [self.delegate webBrowser:self didStartLoadingURL:self.wkWebView.URL];
        }
        if ([self.wkWebView.title isEqualToString:@"集市"] || ([self.webURLString containsString:@"homePage"] && [self.wkWebView.title isEqualToString:@"集市"])) {
            [self.navigationController setNavigationBarHidden:YES animated:false];
            [self.view addSubview:self.progressBar];
            self.progressBar.frame = CGRectMake(0, kStatusBarHeight, __kScreenWidth, 2);
            [self.wkWebView setFrame:CGRectMake(0, kStatusBarHeight, __kScreenWidth, __kScreenHeight-kTabBarHeight-kStatusBarHeight)];//-88
        }else{
            [self.navigationController setNavigationBarHidden:NO animated:false];
            [self.navigationController.navigationBar addSubview:self.progressBar];
            self.progressBar.frame = CGRectMake(0, 0, __kScreenWidth, 2);
            if ([self.wkWebView.title isEqualToString:@"基本信息"] || [self.wkWebView.title isEqualToString:@"银行卡绑定"] || [self.wkWebView.title isEqualToString:@"贷款相关协议"]) {
                [self.wkWebView setFrame:CGRectMake(0, 0, __kScreenWidth, __kScreenHeight-kTopHeight)];
            }else{
                [self.wkWebView setFrame:CGRectMake(0, 0, __kScreenWidth, __kScreenHeight-kTabBarHeight-kTopHeight)];
            }
        }
    }
}
//3、NSLog(@"收到返回内容之后,是否允许加载,允许加载");
//在WkWebView接收到Response后,将Response带的Cookies取出,然后直接放入[NSHTTPCookieStorage sharedHTTPCookieStorage] 容器中,实现cookie共享
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
    YEAFNAppLog(@"3、收到返回内容之后%@------链接%@----%@",self.wkWebView.title,navigationResponse.response.URL.absoluteString,self.wkWebView.URL.absoluteString);
//此处用作去掉首页第一次加载显示箭头,在addspace里面判断self.webURLString
    self.webURLString = self.wkWebView.URL.absoluteString;
    [self addSpaceButton];
    //判断返回
    if ([self.wkWebView.title isEqualToString:@"集市"] && ![self.webURLString containsString:@"homePage"]) {
        LSTabBarViewController.instance.selectedIndex = 2;
//        [self sendRiskDataInfo];
    }else if ([self.wkWebView.title isEqualToString:@"达客良品"] && [self.wkWebView.URL.absoluteString containsString:@"platformmall"]){
        LSTabBarViewController.instance.selectedIndex = 0;
        decisionHandler(WKNavigationResponsePolicyCancel);//是否继续加载
        return;
    }else{

    }

    NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;
    NSArray *cookies =[NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:response.URL];
    for (NSHTTPCookie *cookie in cookies) {
        [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
    }
        decisionHandler(WKNavigationResponsePolicyAllow);//是否继续加载
}

#pragma mark-----------------***二、显示开始加载html CSS js 和图片资源等(JS引擎单线程顺序执行)---------------
#pragma mark - UIWebViewDelegate------------------------------------
// 4、当main frame的导航开始请求时,内容开始返回时会调用此方法。当内容开始到达主帧时被调用(即将完成)
- (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation{
    YEAFNAppLog(@"4");
    YEAFNAppLog(@"当main frame的导航开始请求时,会调用此方法");
}
//5、结束加载内容,页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    YEAFNAppLog(@"5");
    //取出cookie
    NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    //js函数
    NSString *JSFuncString =
    @"function setCookie(name,value,expires)\
    {\
    var oDate=new Date();\
    oDate.setDate(oDate.getDate()+expires);\
    document.cookie=name+'='+value+';expires='+oDate+';path=/'\
    }\
    function getCookie(name)\
    {\
    var arr = document.cookie.match(new RegExp('(^| )'+name+'=({FNXX==XXFN}*)(;|$)'));\
    if(arr != null) return unescape(arr[2]); return null;\
    }\
    function delCookie(name)\
    {\
    var exp = new Date();\
    exp.setTime(exp.getTime() - 1);\
    var cval=getCookie(name);\
    if(cval!=null) document.cookie= name + '='+cval+';expires='+exp.toGMTString();\
    }";
    
    //拼凑js字符串
    NSMutableString *JSCookieString = JSFuncString.mutableCopy;
    for (NSHTTPCookie *cookie in cookieStorage.cookies) {
        NSString *excuteJSString = [NSString stringWithFormat:@"setCookie('%@', '%@', 1);", cookie.name, cookie.value];
        [JSCookieString appendString:excuteJSString];
    }
    //执行js
    [webView evaluateJavaScript:JSCookieString completionHandler:^(id obj, NSError * _Nullable error) {
                YEAFNAppLog(@"执行js函数%@",error);
    }];
    [webView evaluateJavaScript:@"getUser()" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        YEAFNAppLog(@"getUser() 交互函数结果%@----%@",result, error);

    }];
    [self checkWebViewCanGoBack];
    [self updateNavigationBarState];
    self.progressBar.isLoading = NO;
    
    if([self.delegate respondsToSelector:@selector(webBrowser:didFinishLoadingURL:)]) {
        [self.delegate webBrowser:self didFinishLoadingURL:self.wkWebView.URL];
    }
}
//当跳转失败时调用
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation
      withError:(NSError *)error {
    YEAFNAppLog(@"当跳转失败时调用didFailNavigation:%@", error);
    if(webView == self.wkWebView) {
        [self updateNavigationBarState];
        self.progressBar.isLoading = NO;
        [self.progressBar updateProgress:0.0];
        if([self.delegate respondsToSelector:@selector(webBrowser:didFailToLoadURL:error:)]) {
            [self.delegate webBrowser:self didFailToLoadURL:self.wkWebView.URL error:error];
        }
        //        if (!self.reloadView) {
        //            self.reloadView = [[UIView alloc] initWithFrame:CGRectMake(0, kTopHeight, __kScreenWidth, __kScreenHeight-kTopHeight)];
        //
        //            UIImageView *imgView = [MyUtil createImageViewFrame:CGRectMake(0, 0, __kScreenWidth, __kScreenHeight-kTopHeight) imageName:@"no-wl"];
        //            imgView.contentMode = UIViewContentModeCenter;
        //            [self.reloadView addSubview:imgView];
        //        }
        //        [self.view addSubview:self.reloadView];
        //
        //        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(reloadTap:)];
        //        [self.view addGestureRecognizer:tap];
    }
    
    if ([error code] == NSURLErrorCancelled) {
        return ;  //忽略这个错误。
    }

}
// 加载webview内容数据失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation
      withError:(NSError *)error {
    YEAFNAppLog(@"加载webview内容数据失败时调用--------%@",error);

    if(webView == self.wkWebView) {
        [self updateNavigationBarState];
        self.progressBar.isLoading = NO;
        [self.progressBar updateProgress:0.0];
        if([self.delegate respondsToSelector:@selector(webBrowser:didFailToLoadURL:error:)]) {
            [self.delegate webBrowser:self didFailToLoadURL:self.wkWebView.URL error:error];
        }
    }
    if ([error code] == NSURLErrorCancelled) {
        return ;  //忽略这个错误。
    }

}
#pragma mark -证书验证
//iOS8系统下,自建证书的HTTPS链接,不调用此代理方法
//在WKWebView中,WKNavigationDelegate中提供了一个权限认证的代理方法,这是权限认证更为便捷访问HTTPS网页 当webView需要响应身份验证时调用(如需验证服务器证书)
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler
{
    YEAFNAppLog(@"didReceive证书验证");
    
    completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
//        if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
//            if ([challenge previousFailureCount] == 0) {// 如果没有错误的情况下 创建一个凭证,并使用证书
//                NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
//                completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
//            } else {// 验证失败,取消本次验证
//                completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
//            }
//        } else {
//            completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
//        }
}
// 当因为某些问题,导致webView进程终止时触发,比如白屏
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView {
    YEAFNAppLog(@"webView进程终止时触发");
    [webView reload];   //刷新就好了
}
#pragma mark - WKUIDelegate 创建一个新的WebView
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
    YEAFNAppLog(@"创建一个新的WebView");
//    [self.wkWebView loadRequest:[self fixRequest:navigationAction.request]];
    
    if (!navigationAction.targetFrame.isMainFrame) {
        [webView loadRequest:navigationAction.request];
    }
    return nil;
}
//JavaScript调用Obj-C,则是通过web view的代理方法,来接收JavaScript的网络请求从而实现调用
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    NSLog(@"ua=======%@",[request valueForHTTPHeaderField:@"userAgent" ]);
    //判断是否是单击
    if (navigationType == UIWebViewNavigationTypeLinkClicked) {
        NSURL *url = [request URL];
        [[UIApplication sharedApplication]openURL:url];
        return NO;
    }

    return YES;
}
//js -> oc oc接收h5传来的值
#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController
      didReceiveScriptMessage:(WKScriptMessage *)message {
    YEAFNAppLog(@" 从web界面中接收到一个脚本时调用");
    //处理这个事件
    if ([message.name isEqualToString:@"share"]) {
        id body = message.body;
        YEAFNAppLog(@"share分享的内容为:%@", body);
    }
}
// 当main frame接收到服务重定向时,就是跳转到其他的服务器,会回调此方法
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation{
    YEAFNAppLog(@"当main frame接收到服务重定向时,就是跳转到其他的服务器,会回调此方法");
}
#pragma mark - Estimated Progress KVO (WKWebView)监听事件
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
//        YEAFNAppLog(@"监听事件 %@",keyPath);
    if ([keyPath isEqualToString:NSStringFromSelector(@selector(estimatedProgress))] && object == self.wkWebView) {
//        double estimatedProgress = 1.0;

        double estimatedProgress = [change[@"new"] doubleValue];
        [self.progressBar progressUpdate:estimatedProgress];
    }else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

#pragma mark - wkwebView添加的自定义函数
- (void)reloadTap:(UITapGestureRecognizer *)sender {
    YEAFNAppLog(@"重新加载");
    [self.view removeGestureRecognizer:sender];
    if (self.reloadView) {
        [self.reloadView removeFromSuperview];
    }
//    if (self.webURLString.length>0) {
//        NSURL *URL = [NSURL URLWithString:self.webURLString];
//        NSURLRequest *request = [NSURLRequest requestWithURL:URL];
//        [self.wkWebView loadRequest:request];
//    }
}
- (UIView *)reloadView {
    return objc_getAssociatedObject(self, _cmd);
}
- (void)setReloadView:(UIView *)reloadView {
    objc_setAssociatedObject(self, @selector(reloadView), reloadView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
// 注入获取app版本号的js代码
- (NSString *)getVersionInjectionCode {
    NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] ?:@"";
    NSString *injectionCode = [NSString stringWithFormat:@"function getVersion() { return '%@'; }",version];
    return injectionCode;
}
- (NSURLRequest *)fixRequest:(NSURLRequest *)request
{
    NSMutableURLRequest *fixedRequest;
    if ([request isKindOfClass:[NSMutableURLRequest class]]) {
        fixedRequest = (NSMutableURLRequest *)request;
    } else {
        fixedRequest = request.mutableCopy;
    }
    //防止Cookie丢失
    NSDictionary *dict = [NSHTTPCookie requestHeaderFieldsWithCookies:[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies];
    if (dict.count) {
        NSMutableDictionary *mDict = request.allHTTPHeaderFields.mutableCopy;
        [mDict setValuesForKeysWithDictionary:dict];
        fixedRequest.allHTTPHeaderFields = mDict;
    }
    return fixedRequest;
}
#pragma mark - Fake Progress Bar Control (UIWebView)
- (void)fakeProgressBarStopLoading {
    if(self.fakeProgressTimer) {
        [self.fakeProgressTimer invalidate];
    }
    
    if(self.progressView) {
        [self.progressView setProgress:1.0f animated:YES];
        [UIView animateWithDuration:0.3f delay:0.3f options:UIViewAnimationOptionCurveEaseOut animations:^{
            [self.progressView setAlpha:0.0f];
        } completion:^(BOOL finished) {
            [self.progressView setProgress:0.0f animated:NO];
        }];
    }
}
-(UIAlertController *)externalAppPermissionAlertView{
    if (!_externalAppPermissionAlertView) {
        _externalAppPermissionAlertView = [UIAlertController alertControllerWithTitle:@"Leave this app?" message:@"This web page is trying to open an outside app. Are you sure you want to open it?" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
        [_externalAppPermissionAlertView addAction:cancelAction];
        UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            YEAFNAppLog(@"确定");
            [[UIApplication sharedApplication] openURL:self.URLToLaunchWithPermission];
            self.URLToLaunchWithPermission = nil;
        }];
        [_externalAppPermissionAlertView addAction:okAction];
    }
    return _externalAppPermissionAlertView;
}
#pragma mark - External App Support
- (BOOL)externalAppRequiredToOpenURL:(NSURL *)URL {
    NSSet *validSchemes = [NSSet setWithArray:@[@"http", @"https"]];
    return ![validSchemes containsObject:URL.scheme];
}
- (void)launchExternalAppWithURL:(NSURL *)URL {
    self.URLToLaunchWithPermission = URL;
    if (!self.externalAppPermissionAlertView) {
        [self.externalAppPermissionAlertView presentViewController:self animated:YES completion:^{
            
        }];
    }
}
/*!
 *  更新webView的cookie
 */
- (void)updateWebViewCookie
{
    WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource:[self cookieString] injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
    //添加Cookie
    [self.wkWebView.configuration.userContentController addUserScript:cookieScript];
}
- (NSString *)cookieString
{
    NSMutableString *script = [NSMutableString string];
    for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
        // Skip cookies that will break our script
        if ([cookie.value rangeOfString:@"'"].location != NSNotFound) {
            continue;
        }
        // Create a line that appends this cookie to the web view's document's cookies
        [script appendFormat:@"document.cookie='%@'; \n", cookie.da_javascriptString];
    }
    return script;
}

#pragma mark -处理js里的alert
/**
 *  处理js里的alert
 *
 */
- (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:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
    }]];
    [self presentViewController:alert animated:YES completion:nil];
}
/**
 *  处理js里的confirm
 */
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {
    
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:message preferredStyle:UIAlertControllerStyleAlert];
    
    [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(NO);
    }]];
    
    [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(YES);
    }]];
    
    [self presentViewController:alert animated:YES completion:nil];
}

#pragma mark - Dismiss
- (void)dismissAnimated:(BOOL)animated {
    if([self.delegate respondsToSelector:@selector(webBrowserViewControllerWillDismiss:)]) {
        [self.delegate webBrowserViewControllerWillDismiss:self];
    }
    [self.navigationController dismissViewControllerAnimated:animated completion:nil];
}
#pragma mark - Interface Orientation
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAllButUpsideDown;
}

- (BOOL)shouldAutorotate {
    return YES;
}


#pragma mark - Dealloc
- (void)dealloc {
    [self.wkWebView setNavigationDelegate:nil];
    [self.wkWebView setUIDelegate:nil];
    if ([self isViewLoaded]) {
        [self.wkWebView removeObserver:self forKeyPath:NSStringFromSelector(@selector(estimatedProgress))];
    }
    [self.wkWebView stopLoading];
//    [self deleteWebCache];
//    [self cleanCacheAndCookie];
}
#pragma mark -删除缓存
- (void)deleteWebCache {
    
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 9.0) {
        //        NSSet *websiteDataTypes
        //        = [NSSet setWithArray:@[
        //                                WKWebsiteDataTypeDiskCache,
        //                                WKWebsiteDataTypeMemoryCache,
        //                                WKWebsiteDataTypeCookies,
        //                                ]];
        NSSet *websiteDataTypes = [WKWebsiteDataStore allWebsiteDataTypes];
        NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0];
        //// Execute
        [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^{
            // Done
            YEAFNAppLog(@"清除所有缓存");
        }];
    } else {
        NSString *libraryDir = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)[0];
        NSString *bundleId  =  [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
        NSString *webkitFolderInLib = [NSString stringWithFormat:@"%@/WebKit",libraryDir];
        NSString *webKitFolderInCaches = [NSString stringWithFormat:@"%@/Caches/%@/WebKit",libraryDir,bundleId];
        NSError *error;
        /* iOS8.0 WebView Cache的存放路径 */
        [[NSFileManager defaultManager] removeItemAtPath:webKitFolderInCaches error:&error];
        [[NSFileManager defaultManager] removeItemAtPath:webkitFolderInLib error:nil];
    }
}
- (void)cleanCacheAndCookie
{
    //清除cookies
    NSHTTPCookie *cookie;
    NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    for (cookie in [storage cookies])
    {
        [storage deleteCookie:cookie];
    }
    
    [[NSURLCache sharedURLCache] removeAllCachedResponses];
    NSURLCache * cache = [NSURLCache sharedURLCache];
    [cache removeAllCachedResponses];
    [cache setDiskCapacity:0];
    [cache setMemoryCapacity:0];
    
    WKWebsiteDataStore *dateStore = [WKWebsiteDataStore defaultDataStore];
    [dateStore fetchDataRecordsOfTypes:[WKWebsiteDataStore allWebsiteDataTypes]
                     completionHandler:^(NSArray<WKWebsiteDataRecord *> * __nonnull records)
     {
         for (WKWebsiteDataRecord *record  in records)
         {
             
             [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:record.dataTypes
                                                       forDataRecords:@[record]
                                                    completionHandler:^
              {
                  //                  NSLog(@"清除Cookies for %@ deleted successfully",record.displayName);
              }];
         }
     }];
}

#pragma mark - 分享
- (void)showShareItem {
    
    if (self.navigationController) {
        self.navigationController.interactivePopGestureRecognizer.enabled = YES;
        self.navigationItem.rightBarButtonItem = nil;
        if ([self.navigationController.viewControllers indexOfObject:self] > 0) {
            self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"分享" style:UIBarButtonItemStylePlain target:self action:@selector(showShareView)];
        }
    }
}
- (void) showShareView{
}

//当网页中需要调用客户端中的方法时,可以通过下面的方式进行调用
//window.webkit.messageHandlers.test1.postMessage({msg: "test1"});
//window.webkit.messageHandlers.对象名.postMessage(传递参数);
//对象名:就是我们在初始化WKWebView时,通过addScriptMessageHandler注入的js对象名称;
//传递参数:建议用json进行参数的传递,两边约定好的规范,可以提高开发的效率


@end



@implementation UINavigationController(KINWebBrowser)
- (KINWebBrowserViewController *)rootWebBrowser {
    UIViewController *rootViewController = [self.viewControllers objectAtIndex:0];
    return (KINWebBrowserViewController *)rootViewController;
}
@end


上一篇下一篇

猜你喜欢

热点阅读