zoukankan      html  css  js  c++  java
  • iOS学习笔记14-网络(三)WebView

    一、WebView

    WebView就是一个内嵌浏览器控件,在iOS中主要有两种WebView:UIWebViewWKWebView,UIWebView是iOS2之后开始使用,WKWebView是在iOS8开始使用,毫无疑问WKWebView将逐步取代笨重的UIWebView。

    WKWebView的优点:
    1. WKWebView更多的支持HTML5的特性
    2. WKWebView更快,占用内存可能只有UIWebView的1/3 ~ 1/4
    3. WKWebView高达60fps的滚动刷新率和丰富的内置手势
    4. WKWebView具有Safari相同的JavaScript引擎
    5. WKWebView增加了加载进度属性

    尽管讲了这么多WKWebView的优点,但还有很多项目还没有升级到iOS8,UIWebView也还有学习的必要,也可以通过对比WKWebView和UIWebView的使用,加深理解。

    注意:Xcode7禁用了明码的HTTP请求(但不限HTTPS请求),应该在info.plist里添加下面的字段,否则无法响应HTTP请求

    添加App Transport Security Settings,并在其中设置Allow Arbitrary LoadsYES

    二、UIWebView

    1. UIWebView加载请求

    - (void)simpleUIWebViewTest {
        // 1.创建webview,并设置大小,"20"为状态栏高度
        CGFloat width = self.view.frame.size.width;
        CGFloat height = self.view.frame.size.height - 20;
        UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 20, width, height)];
        // 2.创建URL
        NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
        // 3.创建Request
        NSURLRequest *request =[NSURLRequest requestWithURL:url];
        // 4.加载网页
        [webView loadRequest:request];
        // 5.最后将webView添加到界面
        [self.view addSubview:webView];
        self.webView = webView;
    }

    2. UIWebView的实用加载函数

    //加载网络请求
    - (void)loadRequest:(NSURLRequest *)request;
     
    /* 
        功能:加载本地HTML字符串
        string为要加载的本地HTML字符串
        baseURL用来确定htmlString的基准地址,相当于HTML的<base>标签的作用,定义页面中所有链接的默认地址
    */
    - (void)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;
    /* 加载二进制数据 */
    - (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType 
                       characterEncodingName:(NSString *)characterEncodingName 
                                     baseURL:(NSURL *)baseURL;
    下面是加载HTML字符串的例子
    - (void)loadLocalHTMLFileToUIWebView{
        // 获取本地html文件文件路径
        NSString *localHTMLPageName = @"myPage";
        NSString *path = [[NSBundle mainBundle] pathForResource:localHTMLPageName ofType:@"html"];
        // 从html文件中读取html字符串
        NSString *htmlString = [NSString stringWithContentsOfFile:path 
                                                         encoding:NSUTF8StringEncoding 
                                                            error:NULL];
        // 加载本地HTML字符串
        [self.webView loadHTMLString:htmlString baseURL:[[NSBundle mainBundle] bundleURL]];
    }

    UIWebView不仅可以加载HTML页面,还支持pdf、word、txt、各种图片等等的显示。使用loadRequest方法加载的URL是pdf、word、txt、各种图片的URL路径,就可以加载对应的文件,这里就不演示了。

    3. UIWebView的网页导航方法

    我们浏览网页,时常会使用到的刷新网页、前进、后退等导航操作,UIWebView里面也有对应的操作方法。

    #pragma mark - 判断属性
    // 是否可以后退
    @property (nonatomic, readonly, getter=canGoBack) BOOL canGoBack;
    // 是否可以向前
    @property (nonatomic, readonly, getter=canGoForward) BOOL canGoForward;
    // 是否正在加载
    @property (nonatomic, readonly, getter=isLoading) BOOL loading;
    
    #pragma mark - 操作方法
    // 刷新网页
    - (void)reload;
    // 停止加载网页
    - (void)stopLoading;
    // 后退
    - (void)goBack;
    // 前进
    - (void)goForward;

    4. UIWebViewDelegate代理方法

    一共有四个方法:
    //是否允许加载网页,也可获取js要打开的url,通过截取此url可与js交互
    - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request 
                                                     navigationType:(UIWebViewNavigationType)navigationType;
    //开始加载网页
    - (void)webViewDidStartLoad:(UIWebView *)webView;
    //网页加载完成
    - (void)webViewDidFinishLoad:(UIWebView *)webView;
    //网页加载错误
    - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error;

    5. UIWebView和JavaScript交互的方法

    主要有两方面:JS执行OC代码、OC调取写好的JS代码

    • JS执行OC代码:
      JS是不能执行OC代码的,但是可以变相的执行,JS可以将要执行的操作封装到网络请求里面,然后OC拦截这个请求,获取URL里面的字符串解析即可,这里用到代理协议里面的一个方法
      ```objc
    • (BOOL)webView:(UIWebView )webView
      shouldStartLoadWithRequest:(NSURLRequest 
      )request
      navigationType:(UIWebViewNavigationType)navigationType
      ```
    • OC调取写好的JS代码:
      用到WebView的一个方法stringByEvaluatingJavaScriptFromString

      // 实现自动定位JS代码, htmlLocationID为定位的位置(由JS开发人员给出),实现自动定位代码,应该在网页加载完成之后再调用
      NSString *javascriptStr = [NSString stringWithFormat:@"window.location.href = '#%@'",htmlLocationID];
      // webview执行代码
      [self.webView stringByEvaluatingJavaScriptFromString:javascriptStr];
      // 获取网页的title
      NSString *title = [self.webView stringByEvaluatingJavaScriptFromString:@"document.title"];

    6. UIWebView整合功能代码

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        [self initWebView];
    }
    - (void)initWebView{
        // 1.创建webview,并设置大小,"20"为状态栏高度
        CGFloat width = self.view.frame.size.width;
        CGFloat height = self.view.frame.size.height - 20;
        UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0,20,width,height)];
        // 2.创建URL
        NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
        // 3.创建Request
        NSURLRequest *request =[NSURLRequest requestWithURL:url];
        // 4.加载网页
        [webView loadRequest:request];
        // 5.最后将webView添加到界面
        [self.view addSubview:webView];
        self.webView = webView;
        webView.delegate = self;
    }
    #pragma mark 设置前进后退按钮状态
    -(void)setBarButtonStatus{
        if (_webView.canGoBack) {
            _barButtonBack.enabled = YES;
        }else{
            _barButtonBack.enabled = NO;
        }
        if(_webView.canGoForward){
            _barButtonForward.enabled = YES;
        }else{
            _barButtonForward.enabled = NO;
        }
    }
    /*浏览器后退*/
    - (void)clickGoBackBtn{
        if(self.webView.canGoBack){ 
            [self.webView goBack];
        }
    }
    /*浏览器前进*/
    - (void)clickGoForwardBtn{
        if(self.webView.canGoForward){  
            [self.webView goForward];
        }
    }
    #pragma mark - UIWebViewDelegate代理方法
    #pragma mark 开始加载
    //是否允许加载网页,也可获取js要打开的url,通过截取此url可与js交互
    - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request 
                                   navigationType:(UIWebViewNavigationType)navigationType
    {
        //截取URL,这里可以和JS进行交互,但这里没有写,因为会涉及到JS的一些知识,增加复杂性
        NSString *urlString = [request.URL absoluteString];
        urlString = [urlString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        NSArray *urlComps = [urlString componentsSeparatedByString:@"://"];
        NSLog(@"urlString=%@---urlComps=%@",urlString,urlComps);
        return YES;                                             
    }
    //开始加载网页
    - (void)webViewDidStartLoad:(UIWebView *)webView{
        //显示网络请求加载    
        [UIApplication sharedApplication].networkActivityIndicatorVisible = true;
    }
    //网页加载完成
    - (void)webViewDidFinishLoad:(UIWebView *)webView{
        //隐藏网络请求加载图标    
        [UIApplication sharedApplication].networkActivityIndicatorVisible = false;
        [self setBarButtonStatus];
        //取得html内容
        NSLog(@"%@",[self.webView stringByEvaluatingJavaScriptFromString:@"document.title"]);
    }
    //网页加载错误
    - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"系统提示" 
                                                        message:@"网络连接发生错误!" 
                                                       delegate:self 
                                              cancelButtonTitle:nil 
                                              otherButtonTitles:@"确定", nil];    
        [alert show];
    }

    三、WKWebView

    终于轮到WKWebView这个以后时代的主角出场了。要使用WKWebView需要导入 框架,你可以明显地从下面看出我对WKWebView和UIWebView的区别对待,O(∩_∩)O哈哈~

    1. WKWebView加载请求

    和UIWebView用法完全一致:
    #pragma mark - WKWebView简单使用
    - (void)wkWebViewEasyUse
    {
        //1.创建WKWebView
        CGFloat width = self.view.frame.size.width;
        CGFloat height = self.view.frame.size.height - 20;
        WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectMake(0,20,width,height)];
        //2.创建URL
        NSURL *URL = [NSURL URLWithString:@"http://www.baidu.com"];
        //3.创建Request
        NSURLRequest *request = [NSURLRequest requestWithURL:URL];
        //4.加载Request
        [webView loadRequest:request];
        //5.添加到视图
        self.webView = webView;
        [self.view addSubview:webView];
    }

    2. WKWebView的实用加载方法

    UIWebView有的,WKWebView都有,WKWebView多了一个加载文件方法,而且WKWebView的这些加载方法都有返回值。

    /*加载请求*/
    - (WKNavigation *)loadRequest:(NSURLRequest *)request;
    /*加载本地HTML字符串*/
    - (WKNavigation *)loadHTMLString:(NSString *)string 
                             baseURL:(nullable NSURL *)baseURL;
    /*加载本地文件*/
    - (WKNavigation *)loadFileURL:(NSURL*)url 
          allowingReadAccessToURL:(NSURL*)url;
    /* 加载二进制数据 */
    - (WKNavigation *)loadData:(NSData *)data 
                      MIMEType:(NSString *)MIMEType 
         characterEncodingName:(NSString *)characterEncodingName 
                       baseURL:(NSURL *)baseURL;
    loadHTMLString方法的显示效果会有一些区别,看下图:

    我的HTML文件myPage.html如下:
    <html>
        <head><title>Kenshin Cui's Blog</title></head>
        <body style="color:#0092FF;">
            <h1 id="header">I am Kenshin Cui</h1>
            <p>iOS Learn</p>
        </body>
    </html>

    估计两种WebView加载HTML的默认字体样式是不一样的,这里只是说一下

    下面是加载本地文件的实例:
    /* 模拟器调试加载mac本地文件 */
    - (void)loadLocalFile {
        // 1.创建webview,并设置大小,"20"为状态栏高度
        CGFloat width = self.view.frame.size.width;
        CGFloat height = self.view.frame.size.height - 20;
        WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 20, width, height)];
        // 2.创建url  userName:电脑用户名
        NSURL *url = [NSURL fileURLWithPath:@"/Users/userName/Desktop/bigIcon.png"];
        // 3.加载文件
        [webView loadFileURL:url allowingReadAccessToURL:url];
        // 最后将webView添加到界面
        [self.view addSubview:webView];
    }

    3. WKWebView的网页导航方法

    和UIWebView相差不大,多了返回值,多了一些属性,也多了2个方法:

    • reloadFromOrigin,缓存加载
    • goToBackForwardListItem,跳转到指定历史页面
    下面是网页导航方法列表:
    @property (nonatomic, readonly) BOOL canGoBack;
    @property (nonatomic, readonly) BOOL canGoForward;
    @property (nonatomic, readonly, getter=isLoading) BOOL loading;
    - (WKNavigation *)goBack; 
    - (WKNavigation *)goForward;
    - (WKNavigation *)reload; 
    - (void)stopLoading; 
    
    /* 加载进度,取值范围0~1 */
    @property (nonatomic, readonly) double estimatedProgress;
    /* 是否允许左右划手势导航,默认不允许 */
    @property (nonatomic) BOOL allowsBackForwardNavigationGestures;
    /* 访问历史列表 */
    @property (nonatomic, readonly, strong) WKBackForwardList *backForwardList;
    /* 会比较网络数据是否有变化,没有变化则使用缓存,否则从新请求 */
    - (WKNavigation *)reloadFromOrigin;
    /* 比向前向后更强大,可以跳转到某个指定历史页面 */
    - (WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item;

    4. WKWebView的代理

    UIWebView只有一个代理,但WKWebView有好几个,但常用的有2个,
    id<WKNavigationDelegate> navigationDelegateid< WKUIDelegate > UIDelegate

    • WKNavigationDelegate: 最常用,和UIWebViewDelegate功能类似,追踪加载过程,有是否允许加载、开始加载、加载完成、加载失败。
    • WKUIDelegate:UI界面相关,原生控件支持,三种提示框:输入、确认、警告。
    下面列出WKNavigationDelegate的常用代理方法
    /* 1.在发送请求之前,决定是否跳转  */
    - (void)webView:(WKWebView *)webView 
            decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction 
                            decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
    /* 2.页面开始加载 */
    - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation;
    /* 3.在收到服务器的响应头,根据response相关信息,决定是否跳转。 */
    - (void)webView:(WKWebView *)webView 
            decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse 
                              decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;
    /* 4.开始获取到网页内容时返回,需要注入JS,在这里添加 */
    - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation;
    /* 5.页面加载完成之后调用 */
    - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation;
    /* error - 页面加载失败时调用 */
    - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation;
    /* 其他 - 处理服务器重定向Redirect */
    - (void)webView:(WKWebView *)webView 
            didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation;

    我们看看WKUIDelegate的几个代理方法,虽然不是必须实现的,但是如果我们的页面中有调用了JS的alertconfirmprompt方法,我们应该实现下面这几个代理方法,然后在这里调用iOS的弹出窗,因为使用WKWebView后,HTML中的alertconfirmprompt方法调用是不会再弹出窗口了

    下面列出WKUIDelegate的常用代理方法:
    /* 输入框,页面中有调用JS的 prompt 方法就会调用该方法 */
    - (void)webView:(WKWebView *)webView 
            runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt 
                                      defaultText:(nullable NSString *)defaultText 
                                 initiatedByFrame:(WKFrameInfo *)frame 
                                completionHandler:(void (^)(NSString *result))completionHandler;
    /* 确认框,页面中有调用JS的 confirm 方法就会调用该方法 */
    - (void)webView:(WKWebView *)webView 
            runJavaScriptConfirmPanelWithMessage:(NSString *)message 
                                initiatedByFrame:(WKFrameInfo *)frame 
                               completionHandler:(void (^)(BOOL result))completionHandler;
    /* 警告框,页面中有调用JS的 alert 方法就会调用该方法 */
    - (void)webView:(WKWebView *)webView 
            runJavaScriptAlertPanelWithMessage:(NSString *)message 
                              initiatedByFrame:(WKFrameInfo *)frame 
                             completionHandler:(void (^)(void))completionHandler;

    WKWebView还有更多功能,比如和JavaScript互动等,但本人还不太理解,就不写出来忽悠人了。

  • 相关阅读:
    896. Monotonic Array单调数组
    865. Smallest Subtree with all the Deepest Nodes 有最深节点的最小子树
    489. Robot Room Cleaner扫地机器人
    JavaFX
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
  • 原文地址:https://www.cnblogs.com/ming1025/p/6065003.html
Copyright © 2011-2022 走看看