美文网首页
聊聊WKWebView

聊聊WKWebView

作者: WheatDen | 来源:发表于2017-02-13 17:29 被阅读3459次

    前言

    由于之前一直在用UIWebView,所以对于WKWebView只是停留在知道,了解的状态,并未深入的去研究。前天一个项目要求支持iOS8以上,要加入一个web界面。在习惯性使用UIWebView写到一半的时候,突然想使用WKWebView去实现,所以专门花费了些时间去研究了一下WKWebView,很是喜欢。

    正文

    接下来纪录一下使用WKWebView的过程细节。但关于WKWebViewjs互交的部分保留意见,因为并没有深入去研究这一点。

    1、引入WebKit库

    Apple方面为使用WKWebView专门添加了WebKit库,在使用WKWebView时候必须引入WebKit库才可以。

     #import <WebKit/WebKit.h> 
    

    2、初始化WKWebView

    在文档中可以看出,WKWebView的初始化方法有两种:

    - (instancetype)initWithFrame:(CGRect)frame;
    - (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration NS_DESIGNATED_INITIALIZER
    
    • 我们大多使用第一种方式,这也是文档中默认的一种方式。这里不再多说。
    • 关于第二种方式,其实就是在初始化WKWebView时,给webView做一个配置,我这里给出一段简单的配置代码:
    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc]init];
    config.preferences = [WKPreferences new];
    config.preferences.minimumFontSize = 20.f;
    config.preferences.javaScriptEnabled = YES; //The default value is YES
    config.preferences.javaScriptCanOpenWindowsAutomatically = NO;//The default value is NO in iOS and YES in OS X.
    //config.preferences.javaEnabled = NO ; //The default value is NO .不在iphone中使用的方法
    config.userContentController = [WKUserContentController new];  
    self.webView = [[WKWebView alloc]initWithFrame:self.view.bounds configuration:config];
    

    注:其实第一种方式,虽然我们并没有指定初始化的配置,但Apple也为我们指定了一个默认的配置。

    3、加载网页

    方法有几种,我们常用的是

    NSURLRequest *request = [[NSURLRequest alloc]initWithURL:[NSURL URLWithString:@"https://www.baidu.com"]];
    [self.webView loadRequest:request];
    

    剩下的几种为:

        [self.webView loadHTMLString:(nonnull NSString *) baseURL:(nullable NSURL *)];
        
        [self.webView loadFileURL:(nonnull NSURL *) allowingReadAccessToURL:(nonnull NSURL *)];
        
        [self.webView loadData:(nonnull NSData *) MIMEType:(nonnull NSString *) characterEncodingName:(nonnull NSString *) baseURL:(nonnull NSURL *)];
    

    4、加载js代码

    // 图片缩放的js代码
    NSString *js = @"var count = document.images.length;for (var i = 0; i < count; i++) {var image = document.images[i];image.style.width=500;image.style.height=600;};window.alert('找到' + count + '张图');";
    // 根据JS字符串初始化WKUserScript对象
    WKUserScript *script = [[WKUserScript alloc] initWithSource:js injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
    // 根据生成的WKUserScript对象,初始化WKWebViewConfiguration
    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    [config.userContentController addUserScript:script];
    _webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
    [_webView loadHTMLString:@"<head></head>![](https://img.haomeiwen.com/i2269924/034fead1cdf2bfe0.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)"baseURL:nil];
    [self.view addSubview:_webView];
    
    

    5、代理

    WKWebView的代理有两个:WKNavigationDelegateWKUIDelegate

    • 5.1、 WKNavigationDelegate(加载界面时调用的协议方法)

    过程:

    1. 在请求发送之前,决定是否跳转
    2. 页面开始加载时调用
    3. 在收到响应后,决定是否跳转
    4. 内容开始加载时调用
    5. 接收到服务器跳转请求之后调用(不一定调用该方法)
    6. 页面加载完成时调用
    7. 请求失败时调用

    协议方法如下:

    //页面开始加载时调用
    - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation
    {
        NSLog(@"页面开始加载时调用。   2");
    }
    //内容返回时调用,得到请求内容时调用(内容开始加载) -> view的过渡动画可在此方法中加载
    - (void)webView:(WKWebView *)webView didCommitNavigation:( WKNavigation *)navigation
    {
        NSLog(@"内容返回时调用,得到请求内容时调用。 4");
    }
    //页面加载完成时调用
    - (void)webView:(WKWebView *)webView didFinishNavigation:( WKNavigation *)navigation
    {
        NSLog(@"页面加载完成时调用。 5");
    }
    //请求失败时调用
    - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error
    {
        NSLog(@"error1:%@",error);
    }
    -(void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error
    {
        NSLog(@"error2:%@",error);
    }
    //在请求发送之前,决定是否跳转 -> 该方法如果不实现,系统默认跳转。如果实现该方法,则需要设置允许跳转,不设置则报错。
    //该方法执行在加载界面之前
    //Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Completion handler passed to -[ViewController webView:decidePolicyForNavigationAction:decisionHandler:] was not called'
    - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
    {
        //允许跳转
        decisionHandler(WKNavigationActionPolicyAllow);
        
        //不允许跳转
    //    decisionHandler(WKNavigationActionPolicyCancel);
        NSLog(@"在请求发送之前,决定是否跳转。  1");
    }
    //在收到响应后,决定是否跳转(同上)
    //该方法执行在内容返回之前
    - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
    {
        //允许跳转
        decisionHandler(WKNavigationResponsePolicyAllow);
        //不允许跳转
    //    decisionHandler(WKNavigationResponsePolicyCancel);
        NSLog(@"在收到响应后,决定是否跳转。 3");
        
    }
    //接收到服务器跳转请求之后调用
    - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation
    {
        NSLog(@"接收到服务器跳转请求之后调用");
    }
    -(void)webViewWebContentProcessDidTerminate:(WKWebView *)webView
    {
        NSLog(@"webViewWebContentProcessDidTerminate");
    }
    
    
    • 5.2、WKUIDelegate

    这方面包括:创建新的WebView、界面弹出提示框
    创建新的WebView

    // 创建一个新的WebView
    - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;
    

    界面弹出提示框

    系统提供了三种弹出提示框的方法:警告框、确认框、输入框

    直接查看代码如下:

    //警告框
    /**
     webView界面中有弹出警告框时调用
     @param webView             web视图调用委托方法
     @param message             警告框提示内容
     @param frame               主窗口
     @param completionHandler   警告框消失调用
     */
    - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
    {
        completionHandler();
        NSLog(@"警告框");
    }
    //输入框
    /**
     web界面中弹出输入框时调用
     @param webView             web视图调用委托方法
     @param prompt              输入消息的显示
     @param defaultText         初始化时显示的输入文本
     @param frame               主窗口
     @param completionHandler   输入结束后调用
     */
    -(void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler
    {
        NSLog(@"输入框");
        completionHandler(@"http");
    }
    //确认框
    /**
     显示一个JavaScript确认面板
     @param webView             web视图调用委托方法
     @param message             显示的信息
     @param frame               主窗口
     @param completionHandler   确认后完成处理程序调用
     */
    -(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler
    {
        NSLog(@"确认框");
        completionHandler(YES);
    }
    
    

    以上就是WKWebView基本使用方法,其他的不做扩展和补充。也许以后再深入研究时,会有不一样的看法,到时再做推翻或补充。

    以下是个人的一点看法:

    1. WKWebView是在iOS8之后出现的新的网页加载控件,将来也必将取代UIWebView,这是毋庸置疑的事情。
    2. 关于项目优化方面:其实很多人建议在项目中添加WKWebView去替代UIWebView。以未来的发展趋势来看,这点无可厚非。

    我下面想说的是站在老项目并且其中内嵌网页比较多的立场的,iOS8以上使用WKWebViewiOS8以下使用UIWebView。这是目前解决方案的好办法。但维护和优化都需要成本,时间也是成本的一部分。

    这里给出几个讲解WKWebView的🔗,对我帮助很大:

    1. WKWebView的新特性与使用
    2. 使用WKWebView替换UIWebView
    3. UIWebView、WKWebView使用详解及性能分析
    4. WKWebView学习笔记

    相关文章

      网友评论

          本文标题:聊聊WKWebView

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