美文网首页
万能的wkWebview,哈哈

万能的wkWebview,哈哈

作者: 艾希_可可 | 来源:发表于2019-02-26 13:59 被阅读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
    
    
    

    相关文章

      网友评论

          本文标题:万能的wkWebview,哈哈

          本文链接:https://www.haomeiwen.com/subject/byeayqtx.html