WKWebView 小记

作者: 秀才不才 | 来源:发表于2018-08-15 14:13 被阅读27次

    WKWebView 不支持点击处理电话,邮件等格式化的URL,暂时记录下简单的webView处理

    URL 特殊字符编码:
    iOS9.0 之前:
    NSString *encodedString = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,(CFStringRef)urlStr,(CFStringRef)@"!$&'()*+,-./:;=?@_~%#[]",NULL,kCFStringEncodingUTF8));
    iOS9.0 之后:
    NSString *encodedUrl = [url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]
    
    WebView初始化 Session同步
    //初始化时注入sessionID  暂时用着没问题
    NSString *cookieStr = [NSString stringWithFormat:@"document.cookie='%@=%@;path=/';",ShareManager.urlCookie.name,ShareManager.urlCookie.value];
    WKUserScript *wkScript = [[WKUserScript alloc] initWithSource:cookieStr injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
    WKUserContentController *contentC = [[WKUserContentController alloc] init];
    [contentC addUserScript:wkScript];
    WKWebViewConfiguration *wkConfig = [[WKWebViewConfiguration alloc] init];
    wkConfig.userContentController = contentC; 
    webView = [[WKWebView alloc]initWithFrame:self.view.frame configuration:wkConfig];
    
    //URL监听 记着释放
    [self.wkWebView addObserver:self forKeyPath:@"URL" options:NSKeyValueObservingOptionNew context:nil];
    
    WebView frame不正确的时候写了下面方法
    - (void)viewDidLayoutSubviews
    {
        [super viewDidLayoutSubviews];
            
        if (@available(iOS 11.0, *)) {
            CGRect safeFrame = self.view.safeAreaLayoutGuide.layoutFrame;
            [self.wkWebView setFrame:CGRectMake(0, self.backOriginView.frame.origin.y, self.view.frame.size.width, safeFrame.size.height)];
        }
        else
        {
            float height = [[UIApplication sharedApplication] statusBarFrame].size.height;
            if (!self.navigationController.navigationBarHidden) {
                height = 0;
            }
            [self.wkWebView setFrame:CGRectMake(0, height, ScreenWidth, self.view.frame.size.height - height)];
        }
        
    }
    
    WebBridge 注入JS交互
    第三方 `WebViewJavascriptBridge`类
    registerHandler
    callHandler
    
    //JS方法退出Web类需要手动移除,否则类不释放
    [self.bridge removeHandler:js];
    
    可以判断页面退出吗???主要是手势返回
    - (void)viewDidDisappear:(BOOL)animated {
        [super viewDidDisappear:animated];
        if (!self.navigationController && //navigation
            !self.tabBarController &&   //tabbar
            !self.presentingViewController) //present
        {
            [self deleteHanderMethod];
        }
    }
    
    不这样会导致内存泄露???
    在viewWillAppear设置
    if (self.bridge) {
      //不设置 WKWebView 代理不执行
      [self.bridge setWebViewDelegate:self];
    }
    在viewWillDisappear 设置
    [self.bridge setWebViewDelegate:nil];
    
    WebViewDelegate
    //绕过证书认证
    - (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
        if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
            NSURLCredential *card = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust];
            completionHandler(NSURLSessionAuthChallengeUseCredential,card);
        }else {
            completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
        }
    }
    
    //页面开始加载
    - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
      //
    }
    //页面加载完成
    - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
      //
    }
    //页面加载失败
    - (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {
       //
    }
    //收到响应后是否跳转
    - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
        decisionHandler(WKNavigationResponsePolicyAllow);
    }
    -(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
    {
        
        NSURL *linkUrl = navigationAction.request.URL;
        if (navigationAction.navigationType == WKNavigationTypeLinkActivated && [self.urlStr containsString:@"jumpWebUrl=1"]) {
            //url包含jumpWebUrl=1字段 允许跳转外部链接
            if (![linkUrl.host containsString:webView.URL.host]) {
                //当前链接域名不一致 跳转新H5类
                [self goWebViewController:@"" urlStr:navigationAction.request.URL.absoluteString];
                decisionHandler(WKNavigationActionPolicyCancel);
                return;//不return崩溃
            }
        }
        
        NSString *urlScheme = linkUrl.scheme;
        if (urlScheme.length && ([linkUrl.host containsString:@"itunes.apple.com"] || ![urlScheme containsString:@"http"])) {
            
            NSString *scheme = @"";
            if ([urlScheme isEqualToString:@"tel"]) {
                scheme = @"telprompt";//拨打电话☎️会弹窗提示
            } else {
                scheme = urlScheme;
            }
            
            if (IOS10_OR_LATER) {
                [[UIApplication sharedApplication]openURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@:%@",scheme,[linkUrl resourceSpecifier]]] options:@{} completionHandler:nil];
            } else {
                [[UIApplication sharedApplication]openURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@:%@",scheme,[linkUrl resourceSpecifier]]]];
            }
            decisionHandler(WKNavigationActionPolicyCancel);
            return;//不return崩溃
        }
        if (navigationAction.targetFrame == nil) {
            [webView loadRequest:navigationAction.request];
        }
        decisionHandler(WKNavigationActionPolicyAllow);
    }
    
    //弹窗
    - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
      //
    }
    - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {
      //
    }
    - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler { 
      //
    }
    
    
    其他方法
    goBack; //处理显示`返回``关闭`按钮
    
    //禁止缩放 方法不是很完美 
     - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
        return nil;
    }
    

    其他缩放方法(没测试):这里

    WKWebView暂告一段落了

    相关文章

      网友评论

        本文标题:WKWebView 小记

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