上一篇文章我们使用了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的更多相关文章

  1. 使用iOS8 WKWebView的浏览器模块,脉冲动画层-b

    KINWebBrowser是一个可嵌入app的浏览器模块. 它使用iOS 8的 WKWebView API编写,同时在iOS 7上使用UIWebView来兼容. 测试环境: Xcode 6.0 iOS ...

  2. IOS 网络浅析-(十二 UIWebView简介)

    在这篇随笔里,我们只要知道UIWebView是什么就可以了. UIWebView 是苹果提供的用来展示网页的UI控件,它也是最占内存的控件. iOS8.0之后出现了webkit框架,WKWebView ...

  3. [原创]WKWebview点击图片查看大图

    大家都知道,WKWebview是没有查看大图的属性或者方法的,所以只能通过js与之交互来实现这一功能,原理:通过js获取页面的图片,把它存放到数组,给图片添加点击事件,通过index显示大图就行了 其 ...

  4. WKWebview点击图片查看大图

    大家都知道,WKWebview是没有查看大图的属性或者方法的,所以只能通过js与之交互来实现这一功能,原理:通过js获取页面的图片,把它存放到数组,给图片添加点击事件,通过index显示大图就行了 其 ...

  5. DDD 领域驱动设计-看我如何应对业务需求变化,愚蠢的应对?

    写在前面 阅读目录: 具体业务场景 业务需求变化 "愚蠢"的应对 消息列表实现 消息详情页实现 消息发送.回复.销毁等实现 回到原点的一些思考 业务需求变化,领域模型变化了吗? 对 ...

  6. CSS3 3D立方体效果-transform也不过如此

    CSS3系列已经学习了一段时间了,第一篇文章写了一些css3的奇技淫巧,原文戳这里,还获得了较多网友的支持,在此谢过各位,你们的支持是我写文章最大的动力^_^. 那么这一篇文章呢,主要是通过一个3D立 ...

  7. DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践(3)

    上一篇:<DDD 领域驱动设计-谈谈 Repository.IUnitOfWork 和 IDbContext 的实践(2)> 这篇文章主要是对 DDD.Sample 框架增加 Transa ...

  8. DDD 领域驱动设计-两个实体的碰撞火花

    上一篇:<DDD 领域驱动设计-领域模型中的用户设计?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sample(代码已更新) 在 ...

  9. node中的Stream-Readable和Writeable解读

    在node中,只要涉及到文件IO的场景一般都会涉及到一个类-Stream.Stream是对IO设备的抽象表示,其在JAVA中也有涉及,主要体现在四个类-InputStream.Reader.Outpu ...

随机推荐

  1. PowerShell常用的.Net 、COM对象(New-Object、Assembly)、加载程序集

    #新建随机数对象实例:$Ran = New-Object System.Random$Ran.NextDouble() 有时候,要使用的实例的类保存在独立的库文件中,PowerShell默认未加载,会 ...

  2. spring security3.2配置---权限管理

    之前已经在我的博客中发过security的执行流程图了,大家能够先去看看那个图再看这篇.今天我主要在这里贴出了security配置中的几个重要的类和两个xml配置文件,基本上控制权限的就是这几个文件了 ...

  3. android78 Fragment和Activity 传递数据

    Activity: package com.itheima.senddata; import android.os.Bundle; import android.app.Activity; impor ...

  4. mybatis12 Usermapper.xml

    输入和输出映射 通过parameterType完成输入映射,通过resultType和resultMap完成输出映射. 1.1parameterType传递pojo包装对象 可以定义pojo包装类型扩 ...

  5. 磁盘性能指标--IOPS 理论

    机械硬盘的连续读写性很好, 但随机读写性能很差.这是因为磁头移动至正确的磁道上需要时间,随机读写时,磁头不停的移动,时间都花在了磁头寻道上,所以性能不高.  如下图:在存储小文件(图片).OLTP数据 ...

  6. Chapter 5 - How to Detect the Collisions

    Chapter 5 - How to Detect the Collisions Our hero can fire bullets now, but the bullets are only vis ...

  7. Eclipse - 添加 PyDev 插件

    1. 安装PyDev插件 启用Eclipse.在Help菜单中,选择Install New Software···, 然后点击Add按钮.在Location中输入:http://pydev.org/u ...

  8. HTTP基础:URL格式、 HTTP请求、响应、消息

    HTTP URL 格式: http://host[:port][abs_path] 其中http表示要通过HTTP协议来定位网络资源. host表示合法的Internet主机域名或IP地址(以点分十进 ...

  9. angularJs 使用中遇到的问题小结【二:购物车引起的问题思考】

    问题描述 :购物车引起的问题思考 业务逻辑是这样的:我商品加入购物车后,——>点击购物车图标——>进入订单列表(这里的数据只有首次会加载服务器数据,后面就不会执行控制器的方法了,这里的跳转 ...

  10. 读取Properties配置文件

    一,Android中 在Android中读取配置文件,可以使用System.getProperties()方法读取: 1,在res资源目录下,新建一个文件夹 raw,然后在其下创建一个.propert ...