WKWebView-b
上一篇文章我们使用了JavaScriptCore框架重写了之前的示例,iOS8苹果偏爱HTML5,重构了UIWebVIew,给我们带来了WKWebView,使其性能、稳定性、功能大幅度提升,也更好的支持了HTML5的新特性。这篇文章就们就拿WKWebView来小试牛刀
一、WKWebView Framework
WKWebView的14个类与3个协议:
WKBackForwardList: 之前访问过的 web 页面的列表,可以通过后退和前进动作来访问到。
WKBackForwardListItem: webview 中后退列表里的某一个网页。
WKFrameInfo: 包含一个网页的布局信息。
WKNavigation: 包含一个网页的加载进度信息。
WKNavigationAction: 包含可能让网页导航变化的信息,用于判断是否做出导航变化。
WKNavigationResponse: 包含可能让网页导航变化的返回内容信息,用于判断是否做出导航变化。
WKPreferences: 概括一个 webview 的偏好设置。
WKProcessPool: 表示一个 web 内容加载池。
WKUserContentController: 提供使用 JavaScript post 信息和注射 script 的方法。
WKScriptMessage: 包含网页发出的信息。
WKUserScript: 表示可以被网页接受的用户脚本。
WKWebViewConfiguration: 初始化 webview 的设置。
WKWindowFeatures: 指定加载新网页时的窗口属性。
WKWebsiteDataStore: 包含网页数据存储和查找。
WKNavigationDelegate: 提供了追踪主窗口网页加载过程和判断主窗口和子窗口是否进行页面加载新页面的相关方法。
WKUIDelegate: 提供用原生控件显示网页的方法回调。
WKScriptMessageHandler: 提供从网页中收消息的回调方法。
二、WKWebView中的三个代理方法
1. WKNavigationDelegate
该代理提供的方法,可以用来追踪加载过程(页面开始加载、加载完成、加载失败)、决定是否执行跳转。
1
2
3
4
5
6
7
8
|
// 页面开始加载时调用 - ( void )webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation; // 当内容开始返回时调用 - ( void )webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation; // 页面加载完成之后调用 - ( void )webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation; // 页面加载失败时调用 - ( void )webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation; |
页面跳转的代理方法有三种,分为(收到跳转与决定是否跳转两种)
1
2
3
4
5
6
|
// 接收到服务器跳转请求之后调用 - ( void )webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation; // 在收到响应后,决定是否跳转 - ( void )webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:( void (^)(WKNavigationResponsePolicy))decisionHandler; // 在发送请求之前,决定是否跳转 - ( void )webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:( void (^)(WKNavigationActionPolicy))decisionHandler; |
2. WKUIDelegate
创建一个新的WKWebView
1
2
|
// 创建一个新的WebView - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures; |
剩下三个代理方法全都是与界面弹出提示框相关的,针对于web界面的三种提示框(警告框、确认框、输入框)分别对应三种代理方法。
1
2
3
4
5
6
|
// 界面弹出警告框 - ( void )webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:( NSString *)message initiatedByFrame:( void (^)())completionHandler; // 界面弹出确认框 - ( void )webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:( NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:( void (^)( BOOL result))completionHandler; // 界面弹出输入框 - ( void )webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:( NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:( void (^)( NSString * __nullable result))completionHandler; |
3. WKScriptMessageHandler
这个协议中包含一个必须实现的方法,这个方法是native与web端交互的关键,它可以直接将接收到的JS脚本转为OC或Swift对象。
1
2
|
// 从web界面中接收到一个脚本时调用 - ( void )userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message; |
三、使用WKWebView重写
这里我们和之前的界面做了一点改动,之前OC调用JS的时候是进行弹框处理,这里我在写的时候,很郁闷,方法可以调用过去,但是唯独js的alert方法调用没有效果,所以这里采用了输出到div的形式,并增加了一个clear按钮
WKWebView不支持nib文件,所以这里需要使用代码初始化并加载WebView
1
2
3
4
5
6
7
8
9
10
|
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]; config.preferences.minimumFontSize = 18; self .wkWebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, self .view.bounds.size.width, self .view.bounds.size.height/2) configuration:config]; [ self .view addSubview: self .wkWebView]; NSString *filePath = [[ NSBundle mainBundle] pathForResource:@ "index" ofType:@ "html" ]; NSURL *baseURL = [[ NSBundle mainBundle] bundleURL]; [ self .wkWebView loadHTMLString:[ NSString stringWithContentsOfFile:filePath encoding: NSUTF8StringEncoding error: nil ] baseURL:baseURL]; |
OC端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
//1. JS调用OC 添加处理脚本 [userCC addScriptMessageHandler: self name:@ "showMobile" ]; [userCC addScriptMessageHandler: self name:@ "showName" ]; [userCC addScriptMessageHandler: self name:@ "showSendMsg" ]; // 在代理方法中处理对应事件 - ( void )userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { NSLog (@ "%@" , NSStringFromSelector (_cmd)); NSLog (@ "%@" ,message.body); if ([message.name isEqualToString:@ "showMobile" ]) { [ self showMsg:@ "我是下面的小红 手机号是:18870707070" ]; } if ([message.name isEqualToString:@ "showName" ]) { NSString *info = [ NSString stringWithFormat:@ "你好 %@, 很高兴见到你" ,message.body]; [ self showMsg:info]; } if ([message.name isEqualToString:@ "showSendMsg" ]) { NSArray *array = message.body; NSString *info = [ NSString stringWithFormat:@ "这是我的手机号: %@, %@ !!" ,array.firstObject,array.lastObject]; [ self showMsg:info]; } } // 2. native调用js - ( IBAction )btnClick:(UIButton *)sender { if (! self .wkWebView.loading) { if (sender.tag == 123) { [ self .wkWebView evaluateJavaScript:@ "alertMobile()" completionHandler:^( id _Nullable response, NSError * _Nullable error) { //TODO NSLog (@ "%@ %@" ,response,error); }]; } if (sender.tag == 234) { [ self .wkWebView evaluateJavaScript:@ "alertName('小红')" completionHandler: nil ]; } if (sender.tag == 345) { [ self .wkWebView evaluateJavaScript:@ "alertSendMsg('18870707070','周末爬山真是件愉快的事情')" completionHandler: nil ]; } } else { NSLog (@ "the view is currently loading content" ); } } |
JS端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
function clear() { document.getElementById( 'mobile' ).innerHTML = '' document.getElementById( 'name' ).innerHTML = '' document.getElementById( 'msg' ).innerHTML = '' } //OC调用JS的方法列表 function alertMobile() { //这里已经调用过来了 但是搞不明白为什么alert方法没有响应 //alert('我是上面的小黄 手机号是:13300001111') document.getElementById( 'mobile' ).innerHTML = '我是上面的小黄 手机号是:13300001111' } function alertName(msg) { //alert('你好 ' + msg + ', 我也很高兴见到你') document.getElementById( 'name' ).innerHTML = '你好 ' + msg + ', 我也很高兴见到你' } function alertSendMsg(num,msg) { //window.alert('这是我的手机号:' + num + ',' + msg + '!!') document.getElementById( 'msg' ).innerHTML = '这是我的手机号:' + num + ',' + msg + '!!' } //JS响应方法列表 function btnClick1() { window.webkit.messageHandlers.showMobile.postMessage( null ) } function btnClick2() { window.webkit.messageHandlers.showName.postMessage( 'xiao黄' ) } function btnClick3() { window.webkit.messageHandlers.showSendMsg.postMessage([ '13300001111' , 'Go Climbing This Weekend !!!' ]) } |
四、后记
至此,整个系列的示例已完成,过程中收货颇丰。每篇文章都会对知识点进行总结,在文章末尾给出相关链接和示例DEMO的地址,同样本文的示例也已放在GitHub上,需要的同学取走不谢。关于这几篇文章的DEMO,我汇总了下放在了360云盘中,同学们也可以下载此压缩包,解压,对比学习,在看的过程中有什么呢疑问,欢迎在bolg下面留言,若发现文章中有那些地方没有阐述清,或者没有提到也可以留言告诉我
随着H5的强大,hybrid app已经成为当前互联网的大方向,单纯的native app和web app在某些方面显得就很劣势,2015年,Facebook在React.js Conf 2015大会上推出了基于JavaScript的开源框架React Native,使PhoneGap、Cordova时代彻底成为了过去式,React Native有着良好的原生控件的体验,彻底摆脱了UIWebView那让人不爽的性能和交互流程,而且具有良好的拓展和热更新能力,它的功能远远不止这些,有兴趣的同学,可以进入下面的 传送门RN之不归路
戳这里:本文的DEMO地址欢迎star
戳这里:系列示例DEMO合集:https://yunpan.cn/OcMmK58epCKjzn (提取码:e525)
参考资料(戳这里):
> http://nshipster.cn/wkwebkit/
> http://www.huangyibiao.com/archives/742
> https://github.com/reactnativecn/react-native-guide
WKWebView-b的更多相关文章
- 使用iOS8 WKWebView的浏览器模块,脉冲动画层-b
KINWebBrowser是一个可嵌入app的浏览器模块. 它使用iOS 8的 WKWebView API编写,同时在iOS 7上使用UIWebView来兼容. 测试环境: Xcode 6.0 iOS ...
- IOS 网络浅析-(十二 UIWebView简介)
在这篇随笔里,我们只要知道UIWebView是什么就可以了. UIWebView 是苹果提供的用来展示网页的UI控件,它也是最占内存的控件. iOS8.0之后出现了webkit框架,WKWebView ...
- [原创]WKWebview点击图片查看大图
大家都知道,WKWebview是没有查看大图的属性或者方法的,所以只能通过js与之交互来实现这一功能,原理:通过js获取页面的图片,把它存放到数组,给图片添加点击事件,通过index显示大图就行了 其 ...
- WKWebview点击图片查看大图
大家都知道,WKWebview是没有查看大图的属性或者方法的,所以只能通过js与之交互来实现这一功能,原理:通过js获取页面的图片,把它存放到数组,给图片添加点击事件,通过index显示大图就行了 其 ...
- DDD 领域驱动设计-看我如何应对业务需求变化,愚蠢的应对?
写在前面 阅读目录: 具体业务场景 业务需求变化 "愚蠢"的应对 消息列表实现 消息详情页实现 消息发送.回复.销毁等实现 回到原点的一些思考 业务需求变化,领域模型变化了吗? 对 ...
- CSS3 3D立方体效果-transform也不过如此
CSS3系列已经学习了一段时间了,第一篇文章写了一些css3的奇技淫巧,原文戳这里,还获得了较多网友的支持,在此谢过各位,你们的支持是我写文章最大的动力^_^. 那么这一篇文章呢,主要是通过一个3D立 ...
- DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践(3)
上一篇:<DDD 领域驱动设计-谈谈 Repository.IUnitOfWork 和 IDbContext 的实践(2)> 这篇文章主要是对 DDD.Sample 框架增加 Transa ...
- DDD 领域驱动设计-两个实体的碰撞火花
上一篇:<DDD 领域驱动设计-领域模型中的用户设计?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sample(代码已更新) 在 ...
- node中的Stream-Readable和Writeable解读
在node中,只要涉及到文件IO的场景一般都会涉及到一个类-Stream.Stream是对IO设备的抽象表示,其在JAVA中也有涉及,主要体现在四个类-InputStream.Reader.Outpu ...
随机推荐
- Jsp中的EL表达式
EL表达式作用: 向浏览器输出域对象中的变量值或表达式计算的结果!!! 语法: ${变量或表达式} 可以通过page指令来设置EL表示是否启用,false是不启用,true是启用,默认是true &l ...
- thymelef 布局 fragment
需求:布局页面, 把首页分成四个页面: header footer ,content ,aside ,从githua 下载的原型, 所有内容是在一起的,这里拆分, 重用, 减少代码量 做法: 新建页 ...
- wxPython中添加窗口标题图标
这种添加方法可以避免要将应用程序和图标放在同一个目录,可以实现从模块中读取图标 #用于从module中读取ico,避免了要在程序所在路径附上此ico exeName = win32api.GetMod ...
- vmware9.0 安装ios10.8应该注意的地方
今天终于在我的thinkpad t400上面按照好了ios系统 我的硬件配置:cpu:p8700,内存:ddr3,6g 安装的版本:ios10.8 vmware的版本是vmware9.0 安装好的io ...
- HDU2056JAVA
Rectangles Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- android开发之Toast的多种应用
Toast最基本的功能就是弹出一个弱提示,这个很简单我就不说了,说说Toast一些其他的作用. 来公司的时候,公司产品的1.0版本已经发布出去了,但是1.0是一个必须联网才能使用的产品,在2.0中想让 ...
- javascript闭包分析
闭包是什么?闭包是Closure,简而言之,闭包就是: 闭包就是函数的局部变量集合,只是这些局部变量在函数返回后会继续存在. 闭包就是就是函数的“堆栈”在函数返回后并不释放,我们也可以理解为这些函数堆 ...
- 经典关于多态的demo
class Foo { public int a; public Foo() { a = 3; } public int addFive() { a += 5; return a; } public ...
- C#语法糖之第三篇: 匿名类 & 匿名方法
今天时间有点早,所以上来在写一篇文章吧,继续上一篇的文章,在我们平时编程过程中有没有遇到过这样的一个情景,你定义的类只是用来封装一些相关的数据,但并不需要相关联的方法.事件和其他自定义的功能.同时,这 ...
- MongoDB 3.0安全权限访问控制(Windows版)
MongoDB 3.0安全权限访问控制(Windows版) 1.首先,不使用 –auth 参数,启动 mongoDB: mongod --dbpath "d:\mongodb\data\db ...