WKWebView和UIWebView

12 篇文章 0 订阅

UIWebView自iOS2就有,WKWebView从iOS8才有,毫无疑问WKWebView将逐步取代笨重的UIWebView。通过简单的测试即可发现UIWebView占用过多内存,且内存峰值更是夸张。WKWebView网页加载速度也有提升,但是并不像内存那样提升那么多

基本属性:网页加载进度、网页标题,这些网页的最最基本的属性,终于齐了。

前进后退手势:在UIWebView实现过这个功能的我,深知此功能之复杂,当看到这个的时候,整个人都鸟肌了。
WKPreferences:对应WebView的WebViewPreference,相比UIWebView,增加了禁用JavaScript功能,但没有无图模式,差评。
WKUserContentController:JS通讯相关,App注入JS时,可以指定时机(加载开始或加载结束)和范围(MainFrame或所有Frame);另外内置JS Bridge。
WKProcessPool:和多进程模型相关,目前功能未知。
WKBackForwardList:前进后退列表,良心好评。
WKNavigationDelegate:类似于WebView里的WebFrameLoadDelegate,功能稍稍阉割了下,但基本能用。
WKUIDelegate:UI相关的回调。如新窗口打开、页面alert弹框等的处理回调。
更多细节,可以查看WebKit Objective-C Framework Reference。

UIProgressView *progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];

    [self.view addSubview:progressView];

    self.progressView = progressView;

    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    //偏好设置
    config.preferences = [[WKPreferences alloc] init];

    config.preferences.minimumFontSize = 10;

    config.preferences.javaScriptEnabled = YES;
    //表示不能自动打开窗口
    config.preferences.javaScriptCanOpenWindowsAutomatically = NO;

    //web内容处理池,由于没有属性可以设置,也没有方法可以调用,不用手动创建
    config.processPool = [[WKProcessPool alloc] init];


    WKWebView *web2 = [[WKWebView alloc] init];//WithFrame:self.view.bounds configuration:config]; //WithFrame:self.view.bounds

    web2.navigationDelegate = self;
//    web2.UIDelegate = self;

    [web2 addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:NULL];

    [self.view addSubview:web2];
    self.web2 = web2;



    [web2.configuration.userContentController addScriptMessageHandler:self name:@"closeMe"];


    [progressView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.right.equalTo(self.view);

    }];

    [web2 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(progressView.mas_bottom);
        make.left.right.bottom.equalTo(self.view);
    }];
#define mark  设置加载进度条
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{

    if ([keyPath isEqualToString:@"estimatedProgress"] && object == self.web2) {

        self.progressView.alpha = 1.0;
        [self.progressView setProgress:self.web2.estimatedProgress animated:YES];

        if (self.web2.estimatedProgress >= 1.0) {
            [UIView animateWithDuration:0.3 delay:0.3 options:UIViewAnimationOptionCurveEaseOut animations:^{
                self.progressView.alpha = 0.0;
            } completion:^(BOOL finished) {
                [self.progressView setProgress:0.0f animated:YES];
            }];

        }

    }else{
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }

}


 #pragma mark WKNavigationDelegate
 //2.页面开始加载
 - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
 NSLog(@"%s",__func__);
 }
 ///5.页面跳转完成之后调用
 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
 NSLog(@"%s",__func__);
 }

 - (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error{
     NSLog(@"%s----%@",__func__,error);
 }
//证书设置
// 这与用于授权验证的API,与AFN、UIWebView的授权验证API是一样的
 - (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{

     NSLog(@"%s",__func__);
//     NSString *hostName = webView.URL.host;
//     
//     NSString *authenticationMethod = [[challenge protectionSpace] authenticationMethod];
//     if ([authenticationMethod isEqualToString:NSURLAuthenticationMethodDefault]
//         || [authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic]
//         || [authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPDigest]) {
//         
//         NSString *title = @"Authentication Challenge";
//         NSString *message = [NSString stringWithFormat:@"%@ requires user name and password", hostName];
//         UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
//         [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
//             textField.placeholder = @"User";
//             //textField.secureTextEntry = YES;
//         }];
//         [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
//             textField.placeholder = @"Password";
//             textField.secureTextEntry = YES;
//         }];
//         [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
//             
//             NSString *userName = ((UITextField *)alertController.textFields[0]).text;
//             NSString *password = ((UITextField *)alertController.textFields[1]).text;
//             
//             NSURLCredential *credential = [[NSURLCredential alloc] initWithUser:userName password:password persistence:NSURLCredentialPersistenceNone];
//             
//             completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
//             
//         }]];
//         [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
//             completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
//         }]];
//         dispatch_async(dispatch_get_main_queue(), ^{
//             [self presentViewController:alertController animated:YES completion:^{}];
//         });
//         
//     }
//     else if ([authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
//         // needs this handling on iOS 9
//         completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
//         // or, see also http://qiita.com/niwatako/items/9ae602cb173625b4530a#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%B3%E3%83%BC%E3%83%89
//     }
//     else {
//         completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
//     }

     NSURLProtectionSpace *protectionSpace = [challenge protectionSpace];

     id<NSURLAuthenticationChallengeSender> sender = [challenge sender];

     if ([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust])
     {
         SecTrustRef trust = [[challenge protectionSpace] serverTrust];

         NSURLCredential *credential = [[NSURLCredential alloc] initWithTrust:trust];

//         [sender useCredential:credential forAuthenticationChallenge:challenge];
         completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, credential);
     }
     else
     {
//         [sender performDefaultHandlingForAuthenticationChallenge:challenge];
         completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
     }

 }


 // *  在收到响应后,决定是否跳转
 // *
 // *  @param webView            实现该代理的webview
 // *  @param navigationResponse 当前navigation
 // *  @param decisionHandler    是否跳转block

 - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {

     decisionHandler(WKNavigationResponsePolicyAllow);
 }

  // 在收到服务器的响应头,根据response相关信息,决定是否跳转。decisionHandler必须调用,来决定是否跳转,参数WKNavigationActionPolicyCancel取消跳转,WKNavigationActionPolicyAllow允许跳转
 1.
 // *  在发送请求之前,决定是否跳转
 // *
 // *  @param webView          实现该代理的webview
 // *  @param navigationAction 当前navigation
 // *  @param decisionHandler  是否调转block

 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
 NSLog(@"%s",__func__);


     decisionHandler(WKNavigationActionPolicyAllow);
 }
 //4.开始获取页面内容时返回
 - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{

 NSLog(@"%s",__func__);
 }
 //页面跳转失败
 - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error{
     NSLog(@"%s---=====%@",__func__,error);
 }

 #pragma mark WKScriptMessageHandler{

 - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{

        NSLog(@"名称%@ --方法%@",message.name,message.body);

 }


- (void)dealloc{

    if ([self isViewLoaded]) {
        [self.web2 removeObserver:self forKeyPath:@"estimatedProgress"];
    }

    self.web2.navigationDelegate = nil;
    self.web2.UIDelegate = nil;

}

#pragma mark UIWebViewDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
    NSLog(@"%s,-----%@",__func__,request.URL.absoluteString);

    NSLog(@"Did start loading: %@ auth:%d", [[request URL] absoluteString], _authenticated);

    if (!_authenticated) {

        _authenticated = NO;

        _urlConnection = [[NSURLConnection alloc] initWithRequest:_requset delegate:self];

        [_urlConnection start];

        return NO;
    }

    return YES;
}




- (void)webViewDidStartLoad:(UIWebView *)webView{
    NSLog(@"%s",__func__);
    [UMProgressHUD show];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView{
    NSLog(@"%s",__func__);
    [UMProgressHUD dismiss];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
    NSLog(@"%@",error);
    [UMProgressHUD dismiss];
}

//通过connection来设置证书

#pragma mark - NURLConnection delegate

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
{
    NSLog(@"WebController Got auth challange via NSURLConnection");

    if ([challenge previousFailureCount] == 0)
    {
        _authenticated = YES;

        NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];

        [challenge.sender useCredential:credential forAuthenticationChallenge:challenge];

    } else
    {
        [[challenge sender] cancelAuthenticationChallenge:challenge];
    }
}

// We use this method is to accept an untrusted site which unfortunately we need to do, as our PVM servers are self signed.
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
    return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}



#pragma mark - NSURLConnectionDataDelegate

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
{
    NSLog(@"WebController received response via NSURLConnection");

    // remake a webview call now that authentication has passed ok.
    _authenticated = YES;
    [_web1 loadRequest:_requset];

    // Cancel the URL connection otherwise we double up (webview + url connection, same url = no good!)
    [_urlConnection cancel];
}

总的来说,苹果鼓起勇气,第一次开放了如此多的接口,但却仍然不够彻底。这些功能,在UIWebView时代,都可以用私有API解决;而使用了WKWebView之后,在某些方面,依然显得不够用的样子——比方说HTTP和HTTPS验证,仍然没有公开接口可以处理;另外WebResourceLoadDelegate的缺失,也是一大痛点。

2014.7.8 iOS8 beta3 更新Webkit.framework,如下:

同步调用的JS接口。和-[UIWebView stringByEvaluatingJavaScriptFromString:]相比,JS结果是异步而非同步返回的,返回结果为id而非NSString。
WKNavigationDelegate增加了验证回调接口,可以解决HTTP和HTTPS验证问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值