澳门新浦京娱乐场网站-www.146.net-新浦京娱乐场官网
做最好的网站

澳门新浦京娱乐场网站带你走进WKWebView的世界,

好像是macOS10.10之后,以及iOS8之后,新出现的WKWebview组件就迅速的替代了Webview及UIWebView。后者的确存在一些无法解决的bug,诸如架构导致的速度缓慢和内存泄漏。
但无法避免的问题总是有的,比如有些客户端软件,仍然要求兼容老版本的系统,这时候,很不想使用,但也不得不仍然把Webview塞到自己的代码中。
互联网是个喜新厌旧的圈子,网上搜索,几乎只有两类。一是WKWebview的文档,二是iOS类的文档。想要的macOS下面Webview的资料缈如黄鹤。
经过部分只言片语的资料指导和大量的实验,终于完成了工作。所以决定来烧烧冷灶,写出来记录一下。

1.android中利用webview调用网页上的js代码。 Android 中可以通过webview来实现和js的交互,在程序中调用js代码,只需要将webview控件的支持js的属性设置为true,,然后通过loadUrl就可以直接进行调用,如下所示:
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.loadUrl("javascript:test()");

通过学习,你将会学习以下几个方面的内容:

微信iOS客户端将于2017年3月1日前逐步升级为WKWebview内核,需要网页开发者提前做好网站的兼容检查和适配。

1、WKWebview添加手势

1.添加Webview

最简单添加webview的方法就是直接在Interface Builder中把Webview拖入到窗口并且用鼠标拖动到指定位置和指定大小,随后在程序中加上对应的变量:

    @IBOutlet weak var webView: WebView!

如果必须动态程序实现,可以使用window.contentView?.addSubview(webView)把webview控件插入到界面中。

2. 网页上调用android中java代码的方法 在网页中调用java代码,需要在webview控件中添加javascriptInterface。如下所示:

  • **什么是WKWebView以及它和UIWebView的区别是什么 **
  • **认识SafariServices.framework框架,捎带认识UIActivity **
  • 回顾UIWebView在公司工程中的使用
  • WKKit 和 WKWebView简介,特性认识API
  • UIWebView 和WKWebview 以及JSCore JS和OC的相互调用
  • NSURLProtocal的使用
  • WKWebView的一些坑

背景

WKWebView 是苹果在iOS 8中引入的新组件,目的是提供一个现代的支持最新Webkit功能的网页浏览控件,摆脱过去 UIWebView的老、旧、笨,特别是内存占用量巨大的问题。它使用与Safari中一样的Nitro JavaScript引擎,大大提高了页面js执行速度。

UISwipeGestureRecognizer *swipe =[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeAction)];swipe.delegate = self;[wkWebView addGestureRecognizer:swipe];// 允许多个手势并发- gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES;}

2.载入网页

  1. 可以直接导向到某个网页,也可以先在本地启动一个静态页面文件,后续一些工作可以在本地静态网页中用js处理。这种方法是比较多用的,因为程序启动速度会感觉快的很多。
        let path = Bundle.main.path(forResource: "somepage", ofType: "html")
        let url = NSURL.fileURL(withPath: path!)
        let request = URLRequest(url: url);
        self.webView.mainFrame.load(request);
  1. 把somepage.html添加到项目,并在项目设置中Build Phases->Copy Bundle Resources中添加上文件somepage.html,这样最后生成app文件的时候,somepage.html文件才会被打包到其中。
  2. 如果建立的项目使用沙箱(sandbox)模式,现在的应用,如果想上App Store,一般是强制要求使用沙箱的,需要在系统设置的Capabilities中允许incoming network/output networking。否则本地网页没问题,之后的任何网站都无法访问。
  3. 新版本的macOS及iOS都强制必须使用https网页访问,如果需要支持老的http网页,还需要在Info.plist中增加一行:App Transport Security Settings,类型为字典项,其中增加一项:Allow Arbitrary Loads,值为YES。
    完成以上4项,网页已经可以访问了。

复制代码 代码如下:

文章结构目录

切换方法

iOS微信6.5.3版本开始支持开发者手动切换WKWebview和UIWebview,使开发者可提前对WKWebview进行适配。

 

手动切换入口:

在微信会话列表页点击右上角“加号按钮”,选择菜单中的”添加朋友”,在添加朋友界面的搜索框中输入字符串:“:switchweb”,再点击键盘右下角搜索按钮。切换成功后会提示当前使用的内核是UIWebview或是WKWebview。

 

校验切换方法:

通过命令成功切换到WKWebview后,可通过以下方法验证当前网页使用的是否是WKWebview内核。 

微信内任意入口进入任意网页,在网页加载成功后向下拉动页面(或点击网页右上角菜单按钮),使之显示出地址栏,当地址栏以 “此网页由” 开头即为当前使用WKWebview,若以“网页由”则是使用的UIWebview。

 

页面如何判断当前使用的webview内核:

在页面中可通过微信注入的window.__wxjs_is_wkwebview变量判断当前使用的webview内核。 iOS微信6.5.3及其之后的版本 window.__wxjs_is_wkwebview 为true时是使用WKWebview,为 false或者 “undefine”时是 UIWebview 。

前端适配关注的要点

适配的首要原则:若不能区分是WKWebview的新特性新行为还是微信内部逻辑导致原有页面出现问题时,可使用测试页面分别在Safari和微信中的WKWebview内核分别测试,用以快速定位问题产生的原因。

2、WKWebview禁用弹簧滑动

3.从swift调用js

假定在网页中有如下内容:

<script>
function callFromSwift(msg){
    document.getElementById('msgbox').innerHTML=msg;
    return("msg return from js");
}
</script>
<div id='msgbox'></div>

其中定义了一个函数callFromSwift,当被调用的时候,在下面预定义的div中显示传入的字符串,并且返回一个字符串“msg return from js”。
在swift中调用网页中的callFromSwift函数并获取其返回值可以这样做:

        let s=webView.windowScriptObject.evaluateWebScript("callFromSwift('Hello, JavaScript')")
        NSLog(s as! String) //s是js函数的返回结果,可以是多种类型,本例要求是string

mWebView.addJavascriptInterface(new Object() {
            public void clickOnAndroid() {
                mHandler.post(new Runnable() {
                    public void run() {
                        Toast.makeText(Test.this, "测试调用java", Toast.LENGTH_LONG).show();
                    }
                });
            }
        }, "demo");

1.背景

适配指南

切换为WKWebview后,微信中的Webview行为和Safari中保持高度一致,唯一的区别是微信Webview中会注入微信JSBridge相关的脚本。所以适配的重点需要关注以下几个方面: 

一:页面功能是否正常 

二:页面屏幕适配是否正常 三:页面行为是否正常(例如用户在浏览页面时点击返回按钮返回上一个页面时的页面逻辑是否正常) 

四:页面使用的语法是否兼容。 

五:JSSAPI是否正常完美的工作。 

六:重点关注Cookie和LocalStorage等相关的逻辑是否正常。 

七:若服务器有设置返回 Cache-Control缓存有效时间,则需要检查相关逻辑是否正常。

 

正常情况下,你的页面是不需要做特别的适配,但若你的页面有涉及到以下几个受影响的逻辑,则需要根据适配建议进行适配和确认。

 

JSAPI相关适配

一:将不再支持cache 

变化:在WKWebview中将暂不支持cache jsapi。 

适配建议:所有使用此api的开发者可去掉页面相关逻辑。

 

二:页面通过LocalID预览图片 

变化:不再支持通过使用chooseImage api返回的localld以如:”img src=wxLocalResource://50114659201332”的方式预览图片。 

适配建议:

  1. 在iOS微信6.5.3版本及之后的版本中,使用新增的jsapi:getLocalImgData 拿到LocalID对应的图片base64编码后再在前端页面中显示。

2. 如果引入了页面有引入JSSDK,则直接将JSSDK升级为1.2.0最新版本即可帮助页面自动适配。(目前JSSDk线上版本是 1.0.0 和 1.1.0,更新版本为1.2.0 ,  )

 

三:有使用JSSDK,并且使用了wx.config进行权限授权需关注jsapi调用的失败问题 

变化:WKWebview的内部实现变更使我们对微信内的页面jsapi权限管理做了一定逻辑上的调整,有极小可能会发生以前授权正常的jsapi获取权限不正常,从而导致调用jsapi失败。 

适配建议:

1. iOS微信6.5.1,WKWebview在此版本中已知有以下问题:页面使用HTML5的History API pushState; popstate;      replaceState等控制页面导航(典型的如单应用页面),同时使用JSSDK的wx.config为jsapi授权,此时大几率会出现jsapi因为无权限而调用失败的问题。 在6.5.1中页面若可能的情况下,可使用Anchor hash技术替换History技术来解决此问题。

2. iOS微信6.5.2及其之后版本,将不会存在以上问题,但不能100%确认有使用到 history或hash技术更改页面导航地址的页面完全没有此类问题,依然需要开发者注意关注此类问题。

 

Cookie和LocalStorage设置相关

一:退出微信账号后,将会清空所有Cookie和LocalStorage。

 

二:页面功能依赖Cookie,或有涉及到Cookie的相关逻辑 

变化:WKWebview内部实现变更,会影响目前页面Cookie相关的逻辑,例如跨域存取Cookie和页面的资源或图片存储服务器依赖校验Cookie来返回数据等情况。

问题说明:在访问一个页面A时,如果页面A引用了另一个页面B的资源(页面A和B为不同的域名),这时页面B就认为是第三方页面。若在页面B中设置Cookie,就会命中WKWebview下阻止第三方跨域设置Cookie的安全策略,导致问题出现。

适配建议:

在WKWebview中是默认阻止跨域的第三方设置Cookie。所有通过Cookie传递的信息,可通过业务后台存储需要传递的信息,然后给页面一个存储信息相对应的access_token加密码,然后通过Url中加入自己业务的access_token进行页面间信息传递。

如果页面的资源或图片存储的服务器依赖校验Cookie来返回数据的情况,在切换到WKWebview后,在微信内长按保存,或者点击预览大图时,将不会完整的带上所设置的Cookie,会导致图片保存失败或预览失败。除了此种情况,开发者不用担心其他情况下Cookie丢失的问题,所有请求都会带上完整的Cookie。

 

页面视频小窗播放

变化:iOS微信6.5.3及其之后的版本中,Webview默认支持小窗播放。 

澳门新浦京娱乐场网站,开发者需要特别注意小窗播放需要前端同时适配iOS10和iOS10以下的低版本 

适配建议:需要完全按照以下代码设置video标签才可同时兼容不同的iOS版本

<video webkit-playsinline playsinline> </video>

 

WKWebview页面行为与Safari完全一致,会导致页面依赖UIWebview页面行为的逻辑失效或异常:(可根据业务自身逻辑,实现测试页面后分别在Safari和微信WKWebview中验证)

一:Safari或微信WKWebview中 页面A跳转到页面B再返回页面A后不会重新执行Script和Ajax(也不会触发页面reload)。 

二:Safari或微信WKWebview中,在页面弹出输入键盘后,会触发jQuery的resize事件,而在UIWebView下不会。 

三:Safari或微信WKWebview中, window unload 事件在只有刷新才能触发,退出页面或者跳转到其他页面都无法触发。 

四:Safari或微信WKWebview中,极少数情况下某些特殊实现的页面点击事件会失效。

如果有涉及或者遇到以上问题,以兼容Safari行为为准。

wkWebView.scrollView.bounces = NO;

4.从js调用swift

前面的3部分都比较容易,跟WKWebview也大同小异。从JS到swift的调用要复杂的多了。
首先在初始化的时候,要加上一句:

        webView!.frameLoadDelegate=self;

对应的,要在类声明的位置加上一个继承:WebFrameLoadDelegate,随后加入代码:

    //为js对象声明一个接口
    func webView(_ webView: WebView!, didClearWindowObject windowObject: WebScriptObject!, for frame: WebFrame!) {
        self.webView.windowScriptObject.setValue(self, forKey: "swiftHost")
    }
    //这个是基本框架,声明了本类中有两个函数会开放给js对象,并供其调用
    //这里示例了两个,一个是callFromJS1,另一个是quit
    //注意swift中的函数名跟js中的函数名可以不一样,
    //#selector中指明的是swift中声明的函数名,因为selector是object-c中的机制,
    //所以后面在声明真正函数的时候,前面必须加@objc的标志
    //在后面return "xxx"的部分,返回的字符串js中会使用的名字,
    //本例中,swift中函数名跟js中函数名使用了相同的名字,我认为这是好习惯
    override class func webScriptName(for aSelector: Selector) -> String?
    {
        //NSLog("%@",aSelector.description)
        if aSelector == #selector(callFromJS1)
        {
            return "callFromJS1"
        }
        else
        if aSelector == #selector(quit)
        {
            return "quit"
        }
        else
        {
            return nil
        }
    }
    //这个函数顾名思义,应当是不允许在js中调用的,对所有的来值都返回false表示全部允许调用
    override class func isSelectorExcluded(fromWebScript aSelector: Selector) -> Bool
    {
        //NSLog("%@",aSelector.description)
        return false
    }
    //具体的函数
    @objc
    func callFromJS1(message:String)
    {
        NSLog(message)
    }
    @objc
    func quit()
    {
        NSLog("call for quit")
        NSApp.terminate(self);
    }

前三个函数是基本的框架,其中第二个麻烦一些,随后实际上工作的函数没有什么特别。
接着来看看js的部分:

    <a href='javascript:testCallSwift();'>testCallSwift</a><p>
    <a href='javascript:needQuit();'>Quit</a><p>
    <script>
        function testCallSwift(){
            //注意调用方式,window是js的对象
            //swiftHost是swift的接口
            //其后则是声明的swift函数
            window.swiftHost.callFromJS1("hello swift");
        }
        function needQuit(){
            window.swiftHost.quit();
        }
    </script>

在网页中,只需要像调用js方法一样,进行调用就可以
<div id='b'><a onclick="window.demo.clickOnAndroid()">b.c</a></div>

2.移动端展示web方案

--- 2.1 Safari--- 2.2 SFSafariViewController--- 2.3 UIWebView,回顾在公司工程中的使用--- 2.3 UIWebView 接口说明

其他问题

一:页面自定义重载标准方法或者函数时,需要确保不会与微信注入Webview中的JSBridge相关方法冲突,否则会导致页面在微信中的行为异常。

二:强烈建议不要在无法确保页面缓存策略和逻辑与服务器逻辑完全保持一致的情况下冒然设置html页面文件(除了html类型的页面,页面引用的其他资源或脚本按照自身业务合理设置即可)相关的Cache-Control属性。 

典型案例: 

如果第一次访问页面A.html 服务器302跳转到A1.html?uid=111设置Cache-Control: max-age=60,此A1.html的uid参数是服务器设置的111(此时A1.html已经被客户端缓存)。 第二次访问页面A.html ,服务器同样302跳转到A1.html?uid=222,但是此时的A1.html页面的uid参数是222, 客户端带参数完整链接询问服务器缓存是否可用, 服务器返回缓存可用304,但是客户端缓存的A1.html完整链接带的uid参数是111,所以本地找不到数据,此时加载页面就会失败。

3、WKWebview被js调用

5.截获webview每一次访问

跟上面类似,要再增加一个代理:

//初始化的时候增加:
        webView!.policyDelegate=self;

并且声明类的时候多一个继承:WebPolicyDelegate。随后代码中可以实现一个接口:

    func webView(_ webView: WebView!,
                 decidePolicyForNavigationAction actionInformation: [AnyHashable : Any]!,
                 request: URLRequest!,
                 frame: WebFrame!,
                 decisionListener listener: WebPolicyDecisionListener!) {
        NSLog("nav to %@",request.url!.absoluteString)  //这里是将要转向的网址
        listener.use()  //允许访问这个网址
        //listener.ignore()   //不允许访问这个网址则调用这个
    }

也有些程序中为了简化从js调用swift的工作量,会用链接的方式,在链接地址中传入一些指令,就可以用这个函数截获网址并且处理,被处理的网址通常使用listener.ignore()来禁止本次浏览器转向,免得影响当前页面。

3. Java代码调用js并传参 澳门新浦京娱乐场网站带你走进WKWebView的世界,解析Android中webview和js之间的交互。首先需要带参数的js函数,如function test(str),然后只需在调用js时传入参数即可,如下所示:
mWebView.loadUrl("javascript:test('aa')");

3.WKKit& WKWebView

--- 3.1WKKit框架介绍,WKWebView API介绍--- 3.2OC如何给JS注入对象及JS如何给IOS发送数据--- 3.3JS调用alert、confirm、prompt时,不采用JS原生提示,而是使用iOS原生来实现--- 3.4如何监听web内容加载进度、是否加载完成--- 3.5如何处理去跨域问题--- 3.6JS和OC的相互调用--- 3.7WKWebview API问题

window.webkit.messageHandlers.<对象名>.postMessage(body:<数据>)//body中可以直接放js对象,也可以省略body

- userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{ NSLog(@"JS 调用了 %@ 方法,传回参数 %@",message.name,message.body); NSMutableDictionary *dic=[message.body objectForKey:@"body"];}

6.响应js中的警告窗

通常的webview都是不允许js中的alert警告窗的,一方面是为了应用程序整体的效果;另一方面,webview作为一个空间,自己没有UI的控制权,所以类似的工作,是要有应用程序自己实现警告框窗口的。实现警告窗依然要给类增加一个集成WebUIDelegate,并在初始化中增加:

        webView!.uiDelegate=self;

//随后可以实现一个接口:
    func webView(_ sender: WebView!,
                 runJavaScriptAlertPanelWithMessage message: String!,
                 initiatedBy frame: WebFrame!){
        NSLog("msg of alert: %@",message)
    }

如果不满足于只是得到警告消息,要自己在这个函数中使用cocoa的警告窗来显示相关的信息。

4.Js中调用java函数并传参 首先一样需要带参数的函数形式,但需注意此处的参数需要final类型,即得到以后不可修改,如果需要修改其中的值,可以先设置中间变量,然后进行修改。如下所示:

1.背景

自iOS问世以来,iOS 和web总是形影相随。毕竟,当iOS诞生的时候,网站已经有15年的历史了(第一个网站的创建甚至可以追溯到1991年,而iOS在2007年才出现,而那时候还没有AppStore,没有应用分发市场)iPhone出现的时候就已经有很多的web内容了,这样iOS必须提供一种方法来显示web内容。----翻译一位苹果工程师的一段话

4、WKWebview调用js

7.其它

还可以实现从js中访问swift中的变量功能。使用isKeyExcludedFromWebScriptwebScriptNameForKey函数,我用得少,如果需要,参考上面定义函数的方法,查一查官方文档自己来试试吧。

复制代码 代码如下:

2.移动端展示web方案

在iOS 9中,我们有不同的渲染网页内容的选择,根据具体需求,开发人员可以评估不同的选择,选择一个适合他们更好。让我们看看一个开发人员可以采用的不同的解决方案。

让我们看看目前在移动端都有哪些方案:

  • Safari
  • SFSafariViewController
  • UIWebView
  • WKWebview

对于前两种我们都已了解或者掌握,我们先简单的说明一下,我们的重心还是WKWebview上。

NSData *data=[NSJSONSerialization dataWithJSONObject:self->object options:NSJSONWritingPrettyPrinted error:nil];NSString *dataJson=[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]; NSString *dataFunc=[NSString stringWithFormat:@"generalChart",dataJson,(unsigned long)self->chartType]; [self evaluateJavaScript:dataFunc completionHandler:^(id _Nullable param, NSError * _Nullable error) { }];

参考资料:

Swift & JavaScript integration

mWebView.addJavascriptInterface(new Object() {
            public void clickOnAndroid(final int i) {
                mHandler.post(new Runnable() {
                    public void run() {
                                int j = i;
                                j ;
澳门新浦京娱乐场网站带你走进WKWebView的世界,解析Android中webview和js之间的交互。Toast.makeText(Test.this, "测试调用java" String.valueOf(j), Toast.LENGTH_LONG).show();
                    }
                });
            }
        }, "demo");

2.1Safari

我们通常用

 NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"]; [[UIApplication sharedApplication] openURL:url];

这种简单的方式用苹果自带的safari浏览器打开一个网页,从iOS9开始从一个app打开另一个app就像内嵌app一样,可以返回原来的app. 虽然这是一个小小的方案,但是对于跳转到其他app,大家还是不怎么情愿的,因为,我们只想让用户停留在我们的app里。

5、wkwebview手势返回抖屏问题:webview侧滑返回后会接着触发html页面添加的transition动画导致

然后在html页面中,利用如下代码<div id='b'><a onclick="window.demo.clickOnAndroid(2)">b.c</a></div>,
即可实现调用

2.2SFSafariViewController

我们不得不说safari确实很强大,在iOS9,苹果公司给我们提供了一个SafariServices.framework ,这个框架很简单,就几个文件1.SFSafariViewController2.SSReadingList(用户safari阅读列表)3.SFContentBlockerState(safari内容拦击)不用了解

这里只是简单了解下SFSafariViewController,这个控制器的API,很简单。用SFSafariViewController 这种方式可以加载web内容,而且是内置在我们app里的浏览器,但是这个控制器有个致命的弱点就是不能自定义,苹果公司并没有开放出很多API,有一些私有的API可以获得进行自定义,但是我们不能使用,略显尴尬,我想之所以苹果公司不开放很多api的理由,应该主要还是以原生app和safari为主流的原因吧。

 [wkWebView setAllowsBackForwardNavigationGestures:true];//设置手势返回

您可能感兴趣的文章:

  • android WebView加载html5介绍
  • Android中实现Webview顶部带进度条的方法
  • android中webview控件和javascript交互实例
  • Android WebView使用方法详解 附js交互调用方法
  • android webview中使用Java调用JavaScript方法并获取返回值
  • Android中Webview打开网页的同时发送HTTP头信息方法
  • 在Android系统中使用WebViewClient处理跳转URL的方法
  • Android开发之WebView组件的使用解析
  • Android中 webView调用JS出错的解决办法
  • Android混合开发教程之WebView的使用方法总结
2.3UIWebView

废话不多说,我们把重点放在最后WkWebview上,再认识WKWebview之前,我们有必要再简单回顾下UIwebView的使用,以及我们工程里对UIwebview的使用.UIWebview是UIKit框架里的一个视图类, 继承UIView, 整个接口文件也只有100行,里面有一个scrollview的属性,这些都是我们简单的认识。大家感兴趣可以了解下UIwebView的内部实现,后面稍微提一下。

1.公司对UIWebview的简单使用1.1用webView打电话代码如下

 NSString *phoneNum = nil; if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0){ phoneNum = [NSString stringWithFormat:@"telprompt://%@",self.phoneNumber]; } else { phoneNum = [NSString stringWithFormat:@"tel://%@",self.phoneNumber];// 电话号码 } if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:phoneNum]]; } else { UIWebView *callPhoneWebVw = [[UIWebView alloc] initWithFrame:CGRectZero]; self.callwebView = callPhoneWebVw; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:phoneNum]]; [_callwebView loadRequest:request]; }

1.2 封装了 PZLWJSBridgeView ,控件继承UIWebview在家居和知识详情模块,都有用到这个类1.3LLLwebviewcontroller大家都知道,我们最多的是使用这个类,加载wap页面,我们在这里简单看下这个控制器是怎么使用的。其实使用也是蛮简单的,具体步骤如下:1.3.1创建UIwebview1.3.2创建假的进度条,之所以是假的,是因为webview不支持加载进度1.3.3然后就是一些分享业务上的逻辑了(简单调用js代码获取js数据)1.3.4 每次请求的时候有添加cookie的操作,然后dealloc的时候删除 cookie(UIwebview并不支持cookie操作)1.3.5 加载URL过滤,PZLWURLRequestFilter: NSURLProtocol,咱公司对于这个继承自NSURLProtocol的文件也打成了静态库,感兴趣的同学可以去github上找一下, github有实现Demo。但是这个URL过滤,在WKWebView上不支持。我们简单学习一下这个在我们公司封装成静态库的实现过程吧

我们用UIWebview无非就是三个代理和调用javascript代码,而且只是获得html的内容。像这样 :

[self.webView stringByEvaluatingJavaScriptFromString:@"document.getElementById('soufunclient').innerHTML"];

总的来说,UIwebview的使用很简单,这里对UIWebview头文件做了说明

// Copyright  2007-2015 Apple Inc. All rights reserved.//#import <Foundation/Foundation.h>#import <UIKit/UIView.h>#import <UIKit/UIKitDefines.h>#import <UIKit/UIDataDetectors.h>#import <UIKit/UIScrollView.h>NS_ASSUME_NONNULL_BEGINtypedef NS_ENUM(NSInteger, UIWebViewNavigationType) { UIWebViewNavigationTypeLinkClicked,//用户触发了一个链接 UIWebViewNavigationTypeFormSubmitted,//用户提交了一个表单 UIWebViewNavigationTypeBackForward,//用户触击前进前进或返回按钮 UIWebViewNavigationTypeReload,//用户触击重新加载的按钮 UIWebViewNavigationTypeFormResubmitted,//用户重复提交表单 UIWebViewNavigationTypeOther//发生了其他行为} __TVOS_PROHIBITED;//2. 加载内容关于分页显示几种不同类型typedef NS_ENUM(NSInteger, UIWebPaginationMode) { UIWebPaginationModeUnpaginated, UIWebPaginationModeLeftToRight, UIWebPaginationModeTopToBottom, UIWebPaginationModeBottomToTop, UIWebPaginationModeRightToLeft} __TVOS_PROHIBITED;typedef NS_ENUM(NSInteger, UIWebPaginationBreakingMode) { UIWebPaginationBreakingModePage,//默认设置是这个属性,CSS属性以页样式。 UIWebPaginationBreakingModeColumn//当UIWebPaginationBreakingMode设置这个属性的时候,这个页面内容CSS属性以column-break 代替page-breaking样式。} __TVOS_PROHIBITED;@class UIWebViewInternal;@protocol UIWebViewDelegate;NS_CLASS_AVAILABLE_IOS __TVOS_PROHIBITED @interface UIWebView : UIView <NSCoding, UIScrollViewDelegate> @property (nullable, nonatomic, assign) id <UIWebViewDelegate> delegate;@property (nonatomic, readonly, strong) UIScrollView *scrollView NS_AVAILABLE_IOS;- loadRequest:(NSURLRequest *)request;- loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;- loadData:data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)textEncodingName baseURL:baseURL;@property (nullable, nonatomic, readonly, strong) NSURLRequest *request;- reload;- stopLoading;- goBack;- goForward;@property (nonatomic, readonly, getter=canGoBack) BOOL canGoBack;@property (nonatomic, readonly, getter=canGoForward) BOOL canGoForward;@property (nonatomic, readonly, getter=isLoading) BOOL loading;- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;//是否让内容伸缩至适应屏幕当前尺寸@property (nonatomic) BOOL scalesPageToFit;//这个属性如果设置为YES,当进入到页面视图可以自动检测电话号码,让用户可以单机号码进行拨打,不过现已弃用。@property (nonatomic) BOOL detectsPhoneNumbers NS_DEPRECATED_IOS;//这个属性可以设定使电话号码,网址,电子邮件和符合格式的日期等文字变为连接文字。@property (nonatomic) UIDataDetectorTypes dataDetectorTypes NS_AVAILABLE_IOS;//这个属性决定了页面用内嵌HTML5播放视频还是用本地的全屏控制。为了内嵌视频播放,不仅仅需要在这个页面上设置这个属性,还需要在HTML的viedeo元素必须包含webkit-playsinline属性。默认iPhone为NO,iPad为YES。@property (nonatomic) BOOL allowsInlineMediaPlayback NS_AVAILABLE_IOS; // iPhone Safari defaults to NO. iPad Safari defaults to YES//这个属性决定了HTML5视频可以自动播放还是需要用户启动播放。iPhone和iPad默认都是YES。@property (nonatomic) BOOL mediaPlaybackRequiresUserAction NS_AVAILABLE_IOS; // iPhone and iPad Safari both default to YES//这个属性决定了从这个页面是否可以Air Play。iPhone和iPad上都是默认YES。@property (nonatomic) BOOL mediaPlaybackAllowsAirPlay NS_AVAILABLE_IOS; // iPhone and iPad Safari both default to YES//这个值决定了网页内容的渲染是否在把内容全部加到内存中再去处理。如果设置为YES,只有网页内容加载到内存里了才会去渲染。默认为NO@property (nonatomic) BOOL suppressesIncrementalRendering NS_AVAILABLE_IOS; // iPhone and iPad Safari both default to NO//这个属性如果设置为YES,用户必须明确的点击页面上的元素或者相关联的输入页面来显示键盘。如果设置为NO,一个元素的焦点事件就会导致输入视图的显示和自动关联这个元素。@property (nonatomic) BOOL keyboardDisplayRequiresUserAction NS_AVAILABLE_IOS; // default is YES//设置页面分页模型选择。@property (nonatomic) UIWebPaginationMode paginationMode NS_AVAILABLE_IOS;//这个属性决定了CSS属性是采用column-break 还是page-breaking样式。@property (nonatomic) UIWebPaginationBreakingMode paginationBreakingMode NS_AVAILABLE_IOS;//分页的长度@property (nonatomic) CGFloat pageLength NS_AVAILABLE_IOS;//分页之间间距@property (nonatomic) CGFloat gapBetweenPages NS_AVAILABLE_IOS;//分页的个数@property (nonatomic, readonly) NSUInteger pageCount NS_AVAILABLE_IOS;//是否允许画中画播放The default value is YES on devices that support Picture in Picture  mode and NO on all other devices.@property (nonatomic) BOOL allowsPictureInPictureMediaPlayback NS_AVAILABLE_IOS;//3DTouch的预览功能,默认为NO@property (nonatomic) BOOL allowsLinkPreview NS_AVAILABLE_IOS; // default is NO@end__TVOS_PROHIBITED @protocol UIWebViewDelegate <NSObject>@optional- webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;- webViewDidStartLoad:(UIWebView *)webView;- webViewDidFinishLoad:(UIWebView *)webView;- webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error;@endNS_ASSUME_NONNULL_END

现在小编告诉你, 终于进行我们要讲的主题了,不好意思,现在才开始,不过也会很快结束的。

6、wkwebview无法跳转App Store

3 WKKit && WKWebview
- webView:(WKWebView*)webView decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction decisionHandler:(WKNavigationActionPolicy))decisionHandler{ WKNavigationActionPolicy policy =WKNavigationActionPolicyAllow; if([[navigationAction.request.URL host] isEqualToString:@"itunes.apple.com"] &&[[UIApplication sharedApplication] openURL:navigationAction.request.URL]) { policy =WKNavigationActionPolicyCancel; } decisionHandler;}
3.1WKKit框架介绍,WKWebView API介绍

WKWebview在WKKit这个框架里, 苹果将UIWebViewDelegate和UIWebView重构成了14个类与3个协议官方链接

WebKit provides a set of classes to display web content in windows, and implements browser features such as following links when clicked by the user, managing a back-forward list, and managing a history of pages recently visited. WebKit greatly simplifies the complicated process of loading webpages—that is, asynchronously requesting web content from an HTTP server where the response may arrive incrementally, in random order, or partially due to network errors. WebKit also simplifies the process of displaying that content which can contain various MIME types, and compound frame elements each with their own set of scroll bars.

在Overview的时候,苹果官方文档有这样的一段描述。并且还有一个提示

Concurrency NoteThe WebKit framework is not thread-safe. If you call functions or methods in this framework, you must do so exclusively on the main program thread.

不是线程安全的。同样的WebKit框架在MAC app和 iOS APP里是不一样的, 我们可以看到在macAPP里,这个框架是很大的, 里面还包含了子框架, 而且这个框架暴露的头文件也很多,有CSS,DOM等操作的API.

说了这么多,我们稍等一会就只来看看iOS上webkit框架,如果大家刚兴趣可以学习或者了解一下MAC上的webkit框架

WWDC2014-206session:The modern Webkit APi1.Same on iOS and OS X2.Modern3.Streamlined4.Multi-process architecture

澳门新浦京娱乐场网站 1Multi-process architecture

我们首先了解下WKWebView的一些优势:1WKWebview在性能、稳定性上和UIwebview相比2WKWebView更多的支持HTML5的特性3WKWebView更快,占用内存可能只有UIWebView的1/3 ~ 1/44WKWebView高达60fps的滚动刷新率和丰富的内置手势(Built-in gestures)5WKWebView具有Safari相同的JavaScript引擎Nitro(JJT四个进程解释执行优化js代码)(Fast JavaScript)6WKWebView增加了加载进度属性7Easy app-webpage communication8Responsive scrolling9更省电量 battery以上信息可以在WWDC2014-206节-介绍 WebKit modern API 的时候提到。

** po [self.webView recursiveDescription]<UIWebView: 0x14d14130; frame = (0 0; 320 504); layer = <CALayer: 0x12cca690>> | <_UIWebViewScrollView: 0x6c55400; frame = (0 0; 320 504); clipsToBounds = YES; autoresize = H; gestureRecognizers = <NSArray: 0x12c7adf0>; layer = <CALayer: 0x10a4f9c0>; contentOffset: {0, 0}; contentSize: {320, 504}> | | <UIWebBrowserView: 0x69fac00; frame = (0 0; 320 504); text = ''; gestureRecognizers = <NSArray: 0x10ac37f0>; layer = <UIWebLayer: 0x12c9f580>> | | | <LegacyTileHostLayer: 0x14d04c30>  | | | | <LegacyTileLayer: 0x10a99700>  | | <UIImageView: 0x14d0ffd0; frame = (3 498.5; 314 2.5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x14d100b0>> | | <UIImageView: 0x14c4e3a0; frame = (314.5 3; 2.5 498); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x14ceb340>>** po [self.webView recursiveDescription]**<WKWebView: 0x1612c8720; frame = (0 0; 320 504); layer = <CALayer: 0x16127b9b0>> | <WKScrollView: 0x160977600; baseClass = UIWebScrollView; frame = (0 0; 320 504); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x16488d250>; layer = <CALayer: 0x16488a970>; contentOffset: {0, 0}; contentSize: {0, 0}> | | <WKContentView: 0x160a56000; frame = (0 0; 320 504); gestureRecognizers = <NSArray: 0x164887d20>; layer = <CALayer: 0x16127b650>> | | | <UIView: 0x16129d960; frame = (0 0; 320 504); clipsToBounds = YES; layer = <CALayer: 0x1612c3150>> | | | | <UIView: 0x1612c2fe0; frame = (0 0; 320 504); autoresize = W H; layer = <CALayer: 0x16128a9f0>> | | <UIView: 0x164887750; frame = ; opaque = NO; layer = <CALayer: 0x16127a070>> | | <UIImageView: 0x16102fa70; frame = (310 498.5; 7 2.5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x161227960>> | | <UIImageView: 0x163647e60; frame = (314.5 494; 2.5 7); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x1610ac060>>

澳门新浦京娱乐场网站 2UIWebView.png 引用自CocoaChina

UIWebView属于UIKit,封装了WebKit.framework的WebView.WebView组合管理了WebCore.framework的Page,并提供了各种Clients.Page管理了Main Frame,Main Frame管理了sub Frame(FrameTree)我们看一下po出来的视图层级完全不一样,可以说两者关系并不大,WebView继承自WAKView,WAKView类似于NSView,可以做较少的改动使得Mac和iOS共用一套。由UIWebDocumentView对WebView进行操作并接收回调事件,当数据发生变化的时候,就会通知UIWebTiledView重新绘制。UIWebTiledView和WAKWindow这两个类主要负责页面的绘制,包括布局绘图排版,交互等,WAKWindow还会做一些用户操作事件的分派。UIWebBrowserView主要负责: form的自动填充 fixed元素的位置调整JavaScript的手势识别, 键盘弹出时的视图滚动处理,防止遮挡,提供接口让UIWebView获取信息,为显示PDF时添加页号标签

  • -- 引在cocoachina一篇文章

但是我在实际测试的时候, 在真机上出现过收到内存警告。下面两张图片对比下加载www.fang.com的wap页的时候,以及点击wap的时候内存变化的情况。

澳门新浦京娱乐场网站 3UIWebView内存变化情况澳门新浦京娱乐场网站 4WKWebview内存变化情况

从上面一个图片可以看出,刚开始加载网页的时候内存使用是差不多的, 但是当我和wap页面交互的时候,内存变化对于UIWebview来说是巨大的, 对于WkWebView来说相对是较小的。

Class:

WKBackForwardList: 之前访问过的 web 页面的列表,可以通过后退和前进动作来访问到。WKBackForwardListItem: webview 中后退列表里的某一个网页。WKFrameInfo: 包含一个网页的布局信息。WKNavigation: 包含一个网页的加载进度信息。WKNavigationAction: 包含可能让网页导航变化的信息,用于判断是否做出导航变化。WKNavigationResponse: 包含可能让网页导航变化的返回内容信息,用于判断是否做出导航变化。WKPreferences: 概括一个 webview 的偏好设置。WKProcessPool: 表示一个 web 内容加载池。WKUserContentController: 提供使用 JavaScript post 信息和注射 script 的方法。WKScriptMessage: 包含网页发出的信息。WKUserScript: 表示可以被网页接受的用户脚本。WKWebViewConfiguration: 初始化 webview 的设置。WKWindowFeatures: 指定加载新网页时的窗口属性。

WKUserScript:

What Can User Scripts Do?Incredibly powerful• Modify the document• Listen for events• Load resources• Communicate back to your application

Protocal:

WKNavigationDelegate: 提供了追踪主窗口网页加载过程和判断主窗口和子窗口是否进行页面加载新页面的相关方法。WKScriptMessageHandler: 提供从网页中收消息的回调方法。WKUIDelegate: 提供用原生控件显示网页的方法回调。

现在让我们跳到Xcode

/*说明: 1.WKProcessPool@abstract The process pool from which to obtain the view's web content process. @discussion When a web view is initialized, a new web content process will be created for it from the specified pool, or an existing process in that pool will be used. ! A WKProcessPool object represents a pool of web content processes. The process pool associated with a web view is specified by its web view configuration. Each web view is given its own web content process until an implementation-defined process limit is reached; after that, web views with the same process pool end up sharing web content processes. 这个东西好像与cookie有关,一个例子。 2WKUserContentController A WKUserContentController object provides a way for JavaScript to post messages to a web view. The user content controller associated with a web view is specified by its web view configuration. 3 它是用于webview内容交互时选择内容的粒度类型设置。比如说,当使用WKSelectionGranularityDynamic时,而所选择的内容是单个块,这时候granularity可能会是单个字符;当所选择的web内容不限制于某个块时,granularity可能会是单个块。*/#import "LLLWKwebViewViewController.h"//1.第一步导入框架#import <WebKit/WebKit.h>//大家可以看一下,这个Webkit包含了27个文件,我们不能讲的很详细, 只能尽力去说一下@interface LLLWKwebViewViewController ()<WKNavigationDelegate,WKUIDelegate>@property(nonatomic,strong)WKWebView *wkwebview;@end@implementation LLLWKwebViewViewController- viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; // WKWebView *wkView = [[WKWebView alloc]initWithFrame:self.view.bounds]; //3.初始化WKPreferences WKPreferences *preference = [[WKPreferences alloc]init]; preference.minimumFontSize = 0; preference.javaScriptEnabled = YES; preference.javaScriptCanOpenWindowsAutomatically=NO; //4初始化WKUserContentController WKUserContentController *wkuserCVC = [[WKUserContentController alloc]init]; // [wkuserCVC addUserScript:nil]; // [wkuserCVC addScriptMessageHandler:<#(nonnull id<WKScriptMessageHandler>)#> name:<#(nonnull NSString *)#>] //5.WKWebsiteDataStore WKWebsiteDataStore *dataStore = [WKWebsiteDataStore defaultDataStore]; dataStore = [WKWebsiteDataStore nonPersistentDataStore];//适合隐私浏览 NSSet *set = [WKWebsiteDataStore allWebsiteDataTypes]; NSArray *arr = [set allObjects]; // [dataStore fetchDataRecordsOfTypes:(nonnull NSSet<NSString *> *) completionHandler:^(NSArray<WKWebsiteDataRecord *> * _Nonnull) { // }]; // [dataStore removeDataOfTypes:(nonnull NSSet<NSString *> *) forDataRecords:(nonnull NSArray<WKWebsiteDataRecord *> *) completionHandler:^{ //}]; //6WKWebsiteDataRecord // WKWebsiteDataRecord *dataRecord = [[WKWebsiteDataRecord alloc]init]; // dataRecord.dataTypes //2.初始化设置 WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc]init]; config.processPool = [[WKProcessPool alloc]init]; config.preferences = preference; config.userContentController = wkuserCVC; config.websiteDataStore = dataStore; config.suppressesIncrementalRendering = NO;//ioS9 config.applicationNameForUserAgent = @"USer-agent";//ios9 config.allowsAirPlayForMediaPlayback =YES;//airplay isallowed config.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeAll;//ios10 config.allowsInlineMediaPlayback = NO; config.selectionGranularity = WKSelectionGranularityDynamic; config.allowsPictureInPictureMediaPlayback = NO; config.dataDetectorTypes = UIDataDetectorTypePhoneNumber; config.ignoresViewportScaleLimits = NO; WKWebView*wkView = [[WKWebView alloc]initWithFrame:self.view.bounds configuration:config]; self.wkwebview = wkView; WKBackForwardList *list = wkView.backForwardList; WKBackForwardListItem *backlistItem = list.backItem; WKBackForwardListItem *forwardlistItem = list.forwardItem; WKBackForwardListItem *currentlistItem = list.currentItem; WKBackForwardListItem *nextlistItem = [list itemAtIndex:1]; NSArray *backList = list.backList; NSArray *forwardList = list.forwardList; WKNavigation *navigation = [wkView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.fang.com"]]]; wkView.UIDelegate = self; wkView.navigationDelegate = self; [self.view addSubview:wkView]; }#pragma mark---WKNavigationDelegate/*! @abstract Decides whether to allow or cancel a navigation. @param webView The web view invoking the delegate method. @param navigationAction Descriptive information about the action triggering the navigation request. @param decisionHandler The decision handler to call to allow or cancel the navigation. The argument is one of the constants of the enumerated type WKNavigationActionPolicy. @discussion If you do not implement this method, the web view will load the request or, if appropriate, forward it to another application. *///1.The number 1 called//3.The number 3 called//7.The number 7 called- webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(WKNavigationActionPolicy))decisionHandler{ NSLog(@"%s--navigationAction is %@",__FUNCTION__,navigationAction); decisionHandler(WKNavigationActionPolicyAllow);}/*! @abstract Decides whether to allow or cancel a navigation after its response is known. @param webView The web view invoking the delegate method. @param navigationResponse Descriptive information about the navigation response. @param decisionHandler The decision handler to call to allow or cancel the navigation. The argument is one of the constants of the enumerated type WKNavigationResponsePolicy. @discussion If you do not implement this method, the web view will allow the response, if the web view can show it. *///5.The number 5 called- webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(WKNavigationResponsePolicy))decisionHandler{ NSLog(@"%s--navigationAction is %@",__FUNCTION__,navigationResponse); decisionHandler(WKNavigationResponsePolicyAllow); }/*! @abstract Invoked when a main frame navigation starts. @param webView The web view invoking the delegate method. @param navigation The navigation. #########Called when web content begins to load in a web view. *///2.the number 2 called- webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation{ NSLog(@"%s--navigation is %@",__FUNCTION__,navigation);}/*! @abstract Invoked when a server redirect is received for the main frame. @param webView The web view invoking the delegate method. @param navigation The navigation. *///4.The number 4 called- webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation{ NSLog(@"%s--navigation is %@",__FUNCTION__,navigation);}/*! @abstract Invoked when an error occurs while starting to load data for the main frame. @param webView The web view invoking the delegate method. @param navigation The navigation. @param error The error that occurred. */- webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error{ NSLog(@"%s--navigation is %@ and error is %@",__FUNCTION__,navigation,error);}/*! @abstract Invoked when content starts arriving for the main frame. @param webView The web view invoking the delegate method. @param navigation The navigation. ################Called when the web view begins to receive web content. *///6.The number 6 called- webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation{ NSLog(@"%s--navigation is %@",__FUNCTION__,navigation);}/*! @abstract Invoked when a main frame navigation completes. @param webView The web view invoking the delegate method. @param navigation The navigation. */- webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation{ NSLog(@"%s--navigation is %@",__FUNCTION__,navigation);}/*! @abstract Invoked when an error occurs during a committed main frame navigation. @param webView The web view invoking the delegate method. @param navigation The navigation. @param error The error that occurred. */- webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error{ NSLog(@"%s--navigation is %@",__FUNCTION__,navigation);}/*! @abstract Invoked when the web view needs to respond to an authentication challenge. @param webView The web view that received the authentication challenge. @param challenge The authentication challenge. @param completionHandler The completion handler you must invoke to respond to the challenge. The disposition argument is one of the constants of the enumerated type NSURLSessionAuthChallengeDisposition. When disposition is NSURLSessionAuthChallengeUseCredential, the credential argument is the credential to use, or nil to indicate continuing without a credential. @discussion If you do not implement this method, the web view will respond to the authentication challenge with the NSURLSessionAuthChallengeRejectProtectionSpace disposition. */- webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler{ NSLog(@"%s--challenge is %@",__FUNCTION__,challenge); completionHandler(NSURLSessionAuthChallengeUseCredential,nil);}/*! @abstract Invoked when the web view's web content process is terminated. @param webView The web view whose underlying web content process was terminated. */- webViewWebContentProcessDidTerminate:(WKWebView *)webView API_AVAILABLE(macosx, ios{ NSLog(@"%s-",__FUNCTION__);}- didReceiveMemoryWarning { [super didReceiveMemoryWarning];}#pragma mark---WKUIDelegate/*! @abstract Creates a new web view. @param webView The web view invoking the delegate method. @param configuration The configuration to use when creating the new web view. @param navigationAction The navigation action causing the new web view to be created. @param windowFeatures Window features requested by the webpage. @result A new web view or nil. @discussion The web view returned must be created with the specified configuration. WebKit will load the request in the returned web view. If you do not implement this method, the web view will cancel the navigation. */- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{ NSLog(@"%s--configuration is %@ n and navigationAction is %@n and windowFeatures is %@",__FUNCTION__,configuration,navigationAction,windowFeatures); return webView;}/*! @abstract Notifies your app that the DOM window object's close() method completed successfully. @param webView The web view invoking the delegate method. @discussion Your app should remove the web view from the view hierarchy and update the UI as needed, such as by closing the containing browser tab or window. */- webViewDidClose:(WKWebView *)webView API_AVAILABLE(macosx, ios{ NSLog(@"%s-",__FUNCTION__);}/*! @abstract Displays a JavaScript alert panel. @param webView The web view invoking the delegate method. @param message The message to display. @param frame Information about the frame whose JavaScript initiated this call. @param completionHandler The completion handler to call after the alert panel has been dismissed. @discussion For user security, your app should call attention to the fact that a specific website controls the content in this panel. A simple forumla for identifying the controlling website is frame.request.URL.host. The panel should have a single OK button. If you do not implement this method, the web view will behave as if the user selected the OK button. */- webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:completionHandler{ NSLog(@"%s and message is %@ and frame is %@",__FUNCTION__,message,frame);}/*! @abstract Displays a JavaScript confirm panel. @param webView The web view invoking the delegate method. @param message The message to display. @param frame Information about the frame whose JavaScript initiated this call. @param completionHandler The completion handler to call after the confirm panel has been dismissed. Pass YES if the user chose OK, NO if the user chose Cancel. @discussion For user security, your app should call attention to the fact that a specific website controls the content in this panel. A simple forumla for identifying the controlling website is frame.request.URL.host. The panel should have two buttons, such as OK and Cancel. If you do not implement this method, the web view will behave as if the user selected the Cancel button. */- webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(BOOL result))completionHandler{ NSLog(@"%s and message is %@ and frame is %@",__FUNCTION__,message,frame);}/*! @abstract Displays a JavaScript text input panel. @param webView The web view invoking the delegate method. @param message The message to display. @param defaultText The initial text to display in the text entry field. @param frame Information about the frame whose JavaScript initiated this call. @param completionHandler The completion handler to call after the text input panel has been dismissed. Pass the entered text if the user chose OK, otherwise nil. @discussion For user security, your app should call attention to the fact that a specific website controls the content in this panel. A simple forumla for identifying the controlling website is frame.request.URL.host. The panel should have two buttons, such as OK and Cancel, and a field in which to enter text. If you do not implement this method, the web view will behave as if the user selected the Cancel button. */- webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(NSString * _Nullable result))completionHandler{ NSLog(@"%s and prompt is %@ and defaulttext is %@ and frame is %@",__FUNCTION__,prompt,defaultText,frame);}/*! @abstract Allows your app to determine whether or not the given element should show a preview. @param webView The web view invoking the delegate method. @param elementInfo The elementInfo for the element the user has started touching. @discussion To disable previews entirely for the given element, return NO. Returning NO will prevent webView:previewingViewControllerForElement:defaultActions: and webView:commitPreviewingViewController: from being invoked. This method will only be invoked for elements that have default preview in WebKit, which is limited to links. In the future, it could be invoked for additional elements. */- webView:(WKWebView *)webView shouldPreviewElement:(WKPreviewElementInfo *)elementInfo API_AVAILABLE){ NSLog(@"%s-%@",__FUNCTION__, elementInfo); return YES;}/*! @abstract Allows your app to provide a custom view controller to show when the given element is peeked. @param webView The web view invoking the delegate method. @param elementInfo The elementInfo for the element the user is peeking. @param defaultActions An array of the actions that WebKit would use as previewActionItems for this element by default. These actions would be used if allowsLinkPreview is YES but these delegate methods have not been implemented, or if this delegate method returns nil. @discussion Returning a view controller will result in that view controller being displayed as a peek preview. To use the defaultActions, your app is responsible for returning whichever of those actions it wants in your view controller's implementation of -previewActionItems. Returning nil will result in WebKit's default preview behavior. webView:commitPreviewingViewController: will only be invoked if a non-nil view controller was returned. */- (nullable UIViewController *)webView:(WKWebView *)webView previewingViewControllerForElement:(WKPreviewElementInfo *)elementInfo defaultActions:(NSArray<id <WKPreviewActionItem>> *)previewActions API_AVAILABLE){ NSLog(@"%s",__FUNCTION__); return nil;}/*! @abstract Allows your app to pop to the view controller it created. @param webView The web view invoking the delegate method. @param previewingViewController The view controller that is being popped. */- webView:(WKWebView *)webView commitPreviewingViewController:(UIViewController *)previewingViewController API_AVAILABLE){ NSLog(@"%s",__FUNCTION__);}@end

1.通过直接注入js代码, 我们可以做很多事情,上面已经提到1 .1Modify the document1.2 Listen for events1.3 Load resources1.4Communicate back to your application

 WKUserContentController *wkuserCVC = [[WKUserContentController alloc]init]; WKUserScript *script = [[WKUserScript alloc]initWithSource:@"js code" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]; [wkuserCVC addUserScript:script];

2.WKUserContentController是用于给JS注入对象的,注入对象后,JS端就可以使用:

window.webkit.messageHandlers.<name>.postMessage(<messageBody>) 

来调用发送数据给iOS端,比如:

window.webkit.messageHandlers.AppModel.postMessage({body: '传数据'});

OC则是注入对象是,设置了一个代理

#pragma mark @protocol WKScriptMessageHandler <NSObject>/*! @abstract Invoked when a script message is received from a webpage. @param userContentController The user content controller invoking the delegate method. @param message The script message received. */- userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{ NSLog(@"%s and messgae is %@nnn",__FUNCTION__,message);}

现在我们通过上述代码的学习,基本大体了解了WKwebview 的API的使用,这里面大约总共有27多个类, 还有很多的协议。常用的我们首先掌握了, 然后不常用的大家也可以多研究一下。

OC代码咋是收到代理以后,展示原生的控件,代码如下,这里我们

- webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(NSString * _Nullable result))completionHandler{ NSLog(@"%snnn prompt:%@ defaultText:%@ frame:%@",__FUNCTION__,prompt,defaultText,frame); UIAlertController *alertVc = [UIAlertController alertControllerWithTitle:@"prompt" message:[NSString stringWithFormat:@"prompt:%@ndefaultText:%@nframe:%@",prompt,defaultText,frame] preferredStyle:UIAlertControllerStyleAlert]; [alertVc addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { textField.textColor = [UIColor blueColor]; }]; [alertVc addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { completionHandler([[alertVc.textFields lastObject] text]); }]]; [self presentViewController:alertVc animated:YES completion:^{ }];}

WKWebView 有一个属性estimatedProgress,这个就是加载进度。我们利用KVO监听这个属性值的变化,就可以显示加载进度了。

 [self.webview addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];

#pragma mark - WKNavigationDelegate- webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(WKNavigationActionPolicy))decisionHandler { NSString *hostname = navigationAction.request.URL.host.lowercaseString; if (navigationAction.navigationType == WKNavigationTypeLinkActivated && ![hostname containsString:@".baidu.com"]) {// 对于跨域,需要手动跳转 [[UIApplication sharedApplication] openURL:navigationAction.request.URL]; // 不允许web内跳转 decisionHandler(WKNavigationActionPolicyCancel); } else { self.progressView.alpha = 1.0; decisionHandler(WKNavigationActionPolicyAllow); } NSLog(@"%s", __FUNCTION__);}

因为现在WKWebView会忽视默认的网络存储, NSURLCache, NSHTTPCookieStorage, NSCredentialStorage。 目前是这样的,WKWebView有自己的进程,同样也有自己的存储空间用来存储cookie和cache, 其他的网络类如NSURLConnection是无法访问到的。 同时WKWebView发起的资源请求也是不经过NSURLProtocol的,导致无法自定义请求不可否认的,WKWebView确实要好用,APP内的表现也很好,但吐槽的地方也是蛮多的。

 WKWebsiteDataStore *dataStore = [WKWebsiteDataStore defaultDataStore];// dataStore = [WKWebsiteDataStore nonPersistentDataStore];//适合隐私浏览 NSSet *set = [WKWebsiteDataStore allWebsiteDataTypes]; NSArray *arr = [set allObjects]; // [dataStore fetchDataRecordsOfTypes:(nonnull NSSet<NSString *> *) completionHandler:^(NSArray<WKWebsiteDataRecord *> * _Nonnull) { // }]; [dataStore removeDataOfTypes:set forDataRecords:arr completionHandler:^{ }]; [dataStore removeDataOfTypes:set modifiedSince:[NSDate dateWithTimeIntervalSinceNow:-100] completionHandler:^{ }]; 

第一种:有很多的app直接使用在webview的代理中通过拦截的方式与native进行交互,通常是通过拦截url scheme判断是否是我们需要拦截处理的url及其所对应的要处理的功能是什么。任意版本都支持。第二种:iOS7之后出了JavaScriptCore.framework用于与JS交互,但是不支持iOS6,对于还需要支持iOS6的app,就不能考虑这个了。若需要了解,看最后的推荐阅读。第三种:WebViewJavascriptBridge开源库使用,本质上,它也是通过webview的代理拦截scheme,然后注入相应的JS。第四种:react-native

对于第一种,其实在上文的讲解中可能穿插了, 这里简单总结下:1.OC调用JS代码

UIWebview:[webView stringByEvaluatingJavaScriptFromString:@"helloWithName"];WKWebview: [self.webView evaluateJavaScript:@"document.getElementById('soufunclient').innerHTML" completionHandler:^(id _Nullable string, NSError * _Nullable error) { shareContent = [NSString stringWithFormat:@"%@",string]; }];//在这里说明一下,上面的方法是同步的,而WKwebView的方法是异步的。

2JS调用OC代码UIWebView:

//具体让js通知native进行方法调用,我们可以让js产生一个特殊的请求。可以让Native代码可以拦截到,而且不然用户察觉。业界一般的实现方案是在网页中加载一个隐藏的iframe来实现该功能。通过将iframe的src指定为一个特殊的URL,实现在- webView:(UIWebView )webView shouldStartLoadWithRequest:(NSURLRequest )request navigationType:(UIWebViewNavigationType)navigationType;方案中进行拦截处理。对应的js调用代码如下:

 function loadURL { var iFrame; iFrame = document.createElement; iFrame.setAttribute("src", url); iFrame.setAttribute("style", "display:none;"); iFrame.setAttribute("height", "0px"); iFrame.setAttribute("width", "0px"); iFrame.setAttribute("frameborder", "0"); document.body.appendChild; // 发起请求后这个iFrame就没用了,所以把它从dom上移除掉 iFrame.parentNode.removeChild; iFrame = null; }

WKWebView:对于WkwebView我们上面3.2 OC如何给JS注入对象及JS如何给IOS发送数据已经讲到了。

当然这里的总结是最简单的。大家有没有想过,我们怎么才能知道js里的哪些方法OC可以调用,同样OC里哪些模块,JS也知道可以调用呢,React Native 是FaceBook开源的, 大家可以自行百度学习,很牛啊。

对于第二种:javascriptcore.framework我们之前分享JSPatch的时候简单讲过,这里我们再从这篇文章简单讲一下js和OC是通过这个框架相互调用的方法。

对于第三种WebViewJavascriptBridge,第三方框架,挺出名的, 具体的实现是通过webview拦截的方式。我没有细致的去看,就不讲了,感兴趣的同学可以研究。

对于React Native ,这个实现原理很牛掰,大家自己可以搜一下原理看看,这个采用JSX编写,就js和html……,这个东西没有学过,我也不多说了,有时间还是需要学习一下的,有些公司早就应用生产了,解决了想热修复一样的功能。

现在JS和OC交互我们大体就讲完了。1UIWebview拦截 ,执行js代码2WkWebview注入js对象,OC回调,当然我个人认为在服务器发送响应头也是可以做拦截的,和UIwebview一样,不过没有发现网上有这样说的。3就是WebViewJavascriptBridge第三方拦截框架,根本上是对上面的封装4ReacNative 这个就不说了,基本就是用的 JSBridge ,运行时

最后我们来学习这两篇文章1. 文章是一个日本人整理的,是一篇非常不错的文章。

wkwebview无法跳转企业安装

进阶

- webView:(WKWebView*)webView decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction decisionHandler:(WKNavigationActionPolicy))decisionHandler{ NSString *strRequest = [navigationAction.request.URL.absoluteString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; if ([strRequest containsString:@"itms-services"]) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:strRequest]]; } decisionHandler;}
1.使用safari对webview进行调试

感兴趣的同学也可以学习一下

7、wkwebview监听事件

2.WebView加载HTML图片大小自适应与文章自动换行

编程,Ajax,jquery框架,当然如果你对前端感兴趣可以修行一下

[webView addObserver:self forKeyPath:@"canGoBack" options:NSKeyValueObservingOptionNew context:nil];[webView addObserver:self forKeyPath:@"canGoForward" options:NSKeyValueObservingOptionNew context:nil];[webView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:nil];// 进度条[webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];// 只要观察的对象属性有新值就会调用- observeValueForKeyPath:(NSString *)keyPath ofObject:object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:context{ NSLog(@"%d, %d", self.webView.canGoForward, self.webView.canGoBack);}
3.WKWebViewでJavaScript(Alert,Confirm,Prompt)の処理

8、wkwebview关于iPhone X页面适配,全屏显示,发现顶部出现20px的空白添加启动图

4WBWebViewConsole

澳门新浦京娱乐场网站 5增加X启动图

5 iOS10ATS问题

AppDelegate的didFinishLaunchingWithOptions方法中添加

6Cookie问题
 if (@available(iOS 11.0, *)) { [[UIScrollView appearance] setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever]; }

webview添加

if (@available(iOS 11.0, *)) { wkWebView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;}else { self.edgesForExtendedLayout = UIRectEdgeNone;}

9、wkwebview无法加载沙盒中Doc下目录中html,需要放在tem从mainBundle拷贝文件夹到tem

 NSString *strResourcesBundle = [[NSBundle mainBundle] pathForResource:@"dist" ofType:@""]; NSString *path = NSTemporaryDirectory(); NSString *cacheStr=[NSString stringWithFormat:@"%@/dist",path]; NSFileManager * defaultManager = [NSFileManager defaultManager]; NSError *err = nil; [defaultManager copyItemAtPath: strResourcesBundle toPath:cacheStr error: &err]; if{ NSLog(@"复制初始资源文件出错:%@", err); } NSArray *contensArr= [NSArray arrayWithArray:[defaultManager contentsOfDirectoryAtPath:cacheStr error:nil]]; NSLog(@"%@",contensArr);

wkwebview从tem目录下获取加载文件,生成url时使用fileURLWithPath

NSString *cachesPath = NSTemporaryDirectory();//tem文件目录NSString *cacheStr=[NSString stringWithFormat:@"%@dist/index.html",cachesPath];NSURL *url=[NSURL fileURLWithPath: cacheStr];if (@available(iOS 9.0, *)) { [wkWebView loadFileURL:url allowingReadAccessToURL:url];} else { [wkWebView loadRequest:[NSURLRequest requestWithURL:url]];}

获取沙盒地址的方法

NSString *homeDir = NSHomeDirectory();// 获取沙盒主目录路径NSString *cachesPath = NSTemporaryDirectory();//tem文件目录NSString *cachesPath = [NSHomeDirectory()stringByAppendingPathComponent:@"Documents"];//Documents文件目录

10、WKWebView加载不受信任的https造成错误:参考

- webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler{ NSLog(@"didReceiveAuthenticationChallenge"); if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { NSURLCredential *card = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust]; completionHandler(NSURLSessionAuthChallengeUseCredential,card); }}

11、WKWebView隐藏导航栏全屏加载,导航无法手势返回问题,开始以为与setAllowsBackForwardNavigationGestures手势冲突造成,排查后发现是导航隐藏后不支持手势返回,添加以下代码即可,更详细问题参考文章第2点。

隐藏导航代码

[self.navigationController setNavigationBarHidden:NO animated:NO];

支持手势返回代码

 self.navigationController.interactivePopGestureRecognizer.delegate = self; self.navigationController.interactivePopGestureRecognizer.enabled = YES;

12、WKWebView设置setAllowsBackForwardNavigationGestures手势返回事件监听方法:

self.navigationController.interactivePopGestureRecognizer.delegate = self;

-gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{ return YES;}

13、WKWebView在iOS8中使用允许手势返回会报错

if (@available(iOS 9.0, *)) { [wkWebView setAllowsBackForwardNavigationGestures:true];} 

14、WKWebview在iOS11中的适配,顶部会让出状态栏高度

if (@available(iOS 11.0, *)) { wkWebView.scrollView.contentInsetAdjustmentBehavior =UIScrollViewContentInsetAdjustmentNever;}

if (@available(iOS 11.0, *)) { [[UIScrollView appearance] setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];}

15、设置WKWebview是否随键盘上移

//设置wkwebview是否可以随着键盘往上移- viewForZoomingInScrollView:(UIScrollView *)scrollView{ if (isAllowScrollZoom) { return wkWebView; }else{ return nil; }}

16、其它应用后台定位顶端蓝条,导致wkwebview页面向下移动

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didChangeStatusBarFrame:) name:UIApplicationDidChangeStatusBarFrameNotification object:nil];

- didChangeStatusBarFrame:(NSNotification *)notification{ NSValue *statusBarFrameValue = [notification.userInfo valueForKey:UIApplicationStatusBarFrameUserInfoKey]; NSLog(@"Status bar frame changed:%@", NSStringFromCGRect([statusBarFrameValue CGRectValue])); wkWebView.frame=CGRectMake(0.0f, 0.0f, self.view.frame.size.width, self.view.frame.size.height);}

17、wkwebview在iOS12中键盘弹起页面不收回问题

/// 监听将要弹起 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBoardShow) name:UIKeyboardWillShowNotification object:nil]; /// 监听将要隐藏 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBoardHidden) name:UIKeyboardWillHideNotification object:nil];

//iOS12中键盘弹起页面不收回问题#pragma mark - addObserverKeyboard/// 键盘将要弹起- keyBoardShow { CGPoint point = wkWebView.scrollView.contentOffset; keyBoardPoint = point;}/// 键盘将要隐藏- keyBoardHidden { wkWebView.scrollView.contentOffset = keyBoardPoint;}

持续更新中...

本文由澳门新浦京娱乐场网站发布于www.146.net,转载请注明出处:澳门新浦京娱乐场网站带你走进WKWebView的世界,