虽然现在Xcode8已经开始使用WKWebView这个框架进行网页展示,但是UIWebView也有一些常用的方法需要知道,下面就简单展示一下,仅供大家参考

相关知识:1.设置背景透明;2.加载本地HTML页面;3.移除滚动后的外边阴影;4.在Safari中打开链接地址;5.禁用页面滚动弹跳;6.scalesPageToFit属性;7.调用javascript代码;8.javascript调用native代码;9.让UIWebView更加接近native

设置背景透明

  • 设置webview的backgroundColor属性为[UIColor clearColor];

      webView.backgroundColor = [UIColor clearColor];
    
  • 为webview中的HTML页面的body标签添加CSS背景样式设置

      <body style="background-color: transparent">
          ...
      </body>
    
  • 设置webview的opaque属性值为NO

      webView.opaque = NO;
    

加载本地HTML页面

  1. 方式一

     NSString *localHTMLPageName = @"myPage";
    
     NSString *path = [[NSBundle mainBundle] pathForResource:localHTMLPageName ofType:@"html"];
    
     // 从html文件中读取html字符串
     NSFileHandle *readHandle = [NSFileHandle fileHandleForReadingAtPath:path];
    
     NSString *htmlString = [[NSString alloc] initWithData:
                         [readHandle readDataToEndOfFile] encoding:NSUTF8StringEncoding];
     // 或使用
     // NSString *htmlString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
    
     // baseURL用来确定htmlString的基准地址,
     // 相当于HTML的<base>标签的作用,定义页面中所有链接的默认地址。
     [webView loadHTMLString:htmlString baseURL:[[NSBundle mainBundle] bundleURL]];
    
  1. 方式二

     NSString *localHTMLPageName = @"myPage";
    
     NSString *localHTMLPageFilePath = [[NSBundle mainBundle] pathForResource:localHTMLPageName ofType:@"html"];
    
     NSURL *localHTMLPageFileURL = [NSURL fileURLWithPath:localHTMLPageFilePath];
    
     [webView loadRequest:[NSURLRequest requestWithURL:localHTMLPageFileURL]];
    

移除滚动后的外边阴影

UIWebView包含一个scrollView组件,用来将关联web内容实现滚动效果,页面滚动后的UIWebView的面板周围会出现阴影效果,该效果是在四周添加UIImageView实现的,因此移除这种阴影效果的代码如下:

    UIScrollView *scrollView = webView.scrollView;

    for (int i = 0; i < scrollView.subviews.count ; i++) {
        UIView *view = [scrollView.subviews objectAtIndex:i];
        if ([view isKindOfClass:[UIImageView class]]) {
            view.hidden = YES ;
        }
    }

参见Remove UIWebView Shadow?

在Safari中打开链接地址

默认情况下,长按web页面中的链接,系统会自动呼出菜单提供open,copy和cancel选项,但如果要实现触击链接跳转至safari中打开页面该怎么做呢?UIWebViewDelegate协议中,包含

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType

接口,如果为webView添加了delegate对象并实现该接口,那么在webView加载任何一个frame之前都会delegate对象的该方法,该方法的返回值用以控制是否允许加载目标链接页面的内容,返回YES将直接加载内容,NO则反之。并且UIWebViewNavigationType枚举,定义了页面中用户行为的分类,包括

  • UIWebViewNavigationTypeLinkClicked,用户触击了一个链接。
  • UIWebViewNavigationTypeFormSubmitted,用户提交了一个表单。
  • UIWebViewNavigationTypeBackForward,用户触击前进或返回按钮。
  • UIWebViewNavigationTypeReload,用户触击重新加载的按钮。
  • UIWebViewNavigationTypeFormResubmitted,用户重复提交表单
  • UIWebViewNavigationTypeOther,发生其它行为。

因此,实现用户触击UIWebView页面中的链接,并跳至Safari中打开链接页面的步骤如下:

  1. 定义实现UIWebViewDelegate协议的类MyWebViewDelegate(通常是由包含UIWebView的controller中实现UIWebViewDelegate协议)。

  2. 按如下方式实现webView:shouldStartLoadWithRequest:navigationType:接口

     - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
      navigationType:(UIWebViewNavigationType)navigationType
     {
         if ( navigationType == UIWebViewNavigationTypeLinkClicked ) {
             [[UIApplication sharedApplication] openURL:[request URL]];
             return NO;
         }
         return YES;
     }
    
  3. 新建MyWebViewDelegate对象,并赋值给webView的delegate属性

参见:UIWebView open links in Safari

禁用页面滚动弹跳

之前提到UIWebView使用一个UIScrollView对象来关联web页面的内容,通过UIWebView的scrollView属性即可获得该对象,默认情况下网页长度超出设备视口长度后页面会滚动,用户使用手指滚动页面到页面边距并放开手指后页面会产生一个弹跳效果,去除这个效果的方法如下

webView.scrollView.bounces = NO ;

参见:Stop UIWebView from “bouncing” vertically?

scalesPageToFit属性

默认情况下UIWebView加载HTML页面后,会以页面的原始大小进行显示,亦即如果页面的大小超出UIWebView视口大小,UIWebView会出现滚动效果,而且用户只能通过滚动页面来查看不同区域的内容,不能使用手指的捏合手势来放大或缩小页面。通过设置

webView.scalesPageToFit = YES ;

UIWebView可以缩放HTML页面来适配其视口大小,从而达到整屏显示内容的效果,并且用户可以用捏合动作来放大或缩小页面来查看内容。

调用javascript代码

UIWebView提供

- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script

方法,可以在objective-c代码中调用javascript代码,参数script字符串保存了所要执行的js代码字符串,执行结果以字符串形式返回。以获取web页面标题为例,代码如下:

NSString *pageTitle = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];

脚本的代码内容还要依据具体的应用场景。此外,该方法规定执行的脚本时长限定在10s内,为的是防止过长时间的阻塞页面主线程,超过执行时间上线会自动停止脚本运行,并且脚本可分配内存限定在10MB内,超过分配上线将会引发异常。

javascript调用native代码

以上提到,UIWebView加载任何一个页面之前都会调用其代理的

    - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
         navigationType:(UIWebViewNavigationType)navigationType

方法,通过调用参数request对象的URL属性来获取关于本次请求的地址以及参数信息,因此可以通过js代码模拟一次特殊的网络请求来达到调用该代理方法的作用,并通过过滤“特殊的url”来达到有目的性的js代码调用native代码的效果。所谓的“特殊的url”主要的目的是达到一种标识的效果,我们可以规定url的scheme部分,如appscheme://appName?invokeMethodName=objcMethod&paramA=xxx;也可以在常规的url后面附加特殊的参数标识,如http://www.yoursite.com?objecMethodCallFlag=1&methodName=methodA&paramA=xxx。之后根据规定在代理方法中去相应的解析url并做出if else判断即可。常见的调用方式是动态添加一个隐藏的iframe标签到HTML页面,如下:

// js
function invokeObjc(url) {
    var iframe;
    iframe = document.createElement("iframe");
    iframe.setAttribute("src", url);
    iframe.setAttribute("style", "display:none;");
    document.body.appendChild(iframe);
    iframe.parentNode.removeChild(iframe);
}

var url = "appscheme://appName?invokeMethodName=objcMethod&paramA=xxx";

invokeObjc(url);

// objc
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
         navigationType:(UIWebViewNavigationType)navigationType
{
    static NSString *callScheme = @"appscheme";

    static NSString *invokeMethodName = @"invokeMethodName";

    NSString *scheme = request.URL.scheme ;

    if ([callScheme isEqualToString:scheme]) {

        NSString *query = request.URL.query ;

        NSArray *arr = [query componentsSeparatedByString:@"&"];

        __block NSString *methodName = @"" ;

        NSMutableDictionary *params = [NSMutableDictionary new];

        // 未考虑参数的解码操作
        [arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
            NSArray *kv =[obj componentsSeparatedByString:@"="];
            if (kv) {
                if ([invokeMethodName isEqualToString: kv[0]]) {
                    methodName = kv[1];
                }else{
                    [params setObject:kv[1] forKey:kv[0]];
                }
            }
        }];
        // 获得方法名和参数之后,可以添加逻辑判断
        NSLog(@"%@",methodName);
        NSLog(@"%@",params);

        return NO ;
    }
    return YES ;

 }

前面提到的native代码调用js代码的实现方式,结合两种实现方式即完成了js与native代码间的简单的通信操作。

让UIWebView更加接近native

某些情况下,我们既想要UIWebView加载web页面,又想使得所加载的页面的外观和操作行为更加接近native感觉。这时需要使用一些CSS样式来达到这些效果,这些CSS只适用于IOS中的Safari。

  • -webkit-touch-callout

    禁用长按触控对象弹出的菜单。IOS中,当你长按一个触控对象时,如链接,safari会弹出包含链接信息的菜单。禁用此行为CSS代码

      .disable-callout{
          -webkit-touch-callout:none ;
      }
    

    或在webViewDidFinisheLoad中使用

       [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitTouchCallout='none';"];
    
  • -webkit-user-select

    控制用户是否可以选择页面元素内容。IOS中,在页面元素中进行长按操作,safari会弹出菜单,来允许进行选择行为。禁用此行为代码

      .disable-select{
          -webkit-user-select:none;
      }
    

    或在webViewDidFinisheLoad中使用

       [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect='none';"];
    
  • -webkit-tap-highlight-color

    覆盖当用户tap链接或clickable元素时默认产生的高亮颜色(灰色)。如

      .no-highlight{
          -webkit-tap-highlight-color:rgba(0,0,0,0);
      }
    

参见Apple CSS Reference

iOS开发之UIWebView的常见一些用法的更多相关文章

  1. iOS开发之UIWebView

    转自:http://www.cnblogs.com/zhuqil/archive/2011/07/28/2119923.html UIWebView是iOS sdk中一个最常用的控件.是内置的浏览器控 ...

  2. iOS开发之UIWebView自动滑动到顶部-备

    但可以通过subview来操作. 通常用UIWebView加载网页,有时候需要点击一个按钮,或者页面的某个部位,使页面自动滚动到顶部,但是UIWebView不像UIScrollView那么方便.   ...

  3. iOS开发之UIView的常见属性

    1.所有控件都继承自UIView,UIView的常见属性如下: @property(nonatomic,readonly) UIView *superview;获得自己的父控件对象 @property ...

  4. 李洪强iOS开发之FMDB线程安全的用法

    // //  ViewController.m //  04 - FMDB线程安全的用法 // //  Created by 李洪强 on 2017/6/6. //  Copyright © 2017 ...

  5. iOS开发之cell位置contentOffset的用法

    @property(nonatomic)         CGPoint                      contentOffset;                  // default ...

  6. iOS开发之Socket通信实战--Request请求数据包编码模块

    实际上在iOS很多应用开发中,大部分用的网络通信都是http/https协议,除非有特殊的需求会用到Socket网络协议进行网络数 据传输,这时候在iOS客户端就需要很好的第三方CocoaAsyncS ...

  7. iOS开发之loadView、viewDidLoad及viewDidUnload的关系

    iOS开发之loadView.viewDidLoad及viewDidUnload的关系 iOS开发之loadView.viewDidLoad及viewDidUnload的关系    标题中所说的3个方 ...

  8. iOS开发之info.pist文件和.pch文件

    iOS开发之info.pist文件和.pch文件 如果你是iOS开发初学者,不用过多的关注项目中各个文件的作用.因为iOS开发的学习路线起点不在这里,这些文件只会给你学习带来困扰. 打开一个项目,我们 ...

  9. iOS 开发之Block

    iOS 开发之Block 一:什么是Block.Block的作用 UI开发和网络常见功能的实现回调,按钮事件的处理方法是回调方法. 1.     按钮事件 target action 机制. 它是将一 ...

随机推荐

  1. 用js来实现那些数据结构07(链表01-链表的实现)

    前面讲解了数组,栈和队列.其实大家回想一下.它们有很多相似的地方.甚至栈和队列这两种数据结构在js中的实现方式也都是基于数组.无论增删的方式.遵循的原则如何,它们都是有序集合的列表.在js中,我们新建 ...

  2. Android ART、Dalvik在multidex上的差异、关联

    为提升应用运行性能,谷歌官方从5.0(api level:21)版本开始,将虚拟机运行环境默认为ART, 此处主要研究ART.Dalvik在multidex处理上的差异和关联,做了一个简单的手绘,如下 ...

  3. codeforces 651C Watchmen

    Watchmen are in a danger and Doctor Manhattan together with his friend Daniel Dreiberg should warn t ...

  4. hdu 5656 CA Loves GCD(n个任选k个的最大公约数和)

    CA Loves GCD  Accepts: 64  Submissions: 535  Time Limit: 6000/3000 MS (Java/Others)  Memory Limit: 2 ...

  5. [NOI2011]

    来自FallDream的博客,未经允许,请勿转载,谢谢. 省选完挂.但是善良的教练今天丢了一套NOI2011给我们训练 6道题233(虽然一道题做过了,一道题普及组的都会,就算是4道吧) 熬了一天,总 ...

  6. [BZOJ]1011 遥远的行星(HNOI2008)

    由eps引发的血案. Description 直线上N颗行星,X=i处有行星i,行星J受到行星I的作用力,当且仅当i<=A*J.此时J受到作用力的大小为 Fi->j=Mi*Mj/(j-i) ...

  7. 关于HttpClient重试策略的研究

    一.背景 由于工作上的业务本人经常与第三方系统交互,所以经常会使用HttpClient与第三方进行通信.对于交易类的接口,订单状态是至关重要的. 这就牵扯到一系列问题: HttpClient是否有默认 ...

  8. Angular中 build的时候遇到的错误--There are multiple modules with names that only differ in casing

    今天早上遇到一个Angular的编译的时候的错误 具体信息: There are multiple modules with names that only differ in casing.This ...

  9. C++是跨平台的语言

    最开始学习Java时,老师就说Java是跨平台的,而c++不是,这里要纠正一下观点,c++也是跨平台的,只不过是实现跨平台的方式不同而已. 1.平台 一般我们把CPU处理器与操作系统的整体叫平台.不同 ...

  10. P2P技术概要

          P2P(Peer to Peer)也就是 对等网络,即对等计算机网络,是一种在对等者(Peer)之间分配任务和工作负载的分布式应用架构[1]  ,是对等计算模型在应用层形成的一种组网或网络 ...