上一篇文章我们使用了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

该代理提供的方法,可以用来追踪加载过程(页面开始加载、加载完成、加载失败)、决定是否执行跳转。

// 页面开始加载时调用
- (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;

页面跳转的代理方法有三种,分为(收到跳转与决定是否跳转两种)

// 接收到服务器跳转请求之后调用
- (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

// 创建一个新的WebView
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;

剩下三个代理方法全都是与界面弹出提示框相关的,针对于web界面的三种提示框(警告框、确认框、输入框)分别对应三种代理方法。

// 界面弹出警告框
- (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对象。

// 从web界面中接收到一个脚本时调用
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;

  

三、使用WKWebView重写

这里我们和之前的界面做了一点改动,之前OC调用JS的时候是进行弹框处理,这里我在写的时候,很郁闷,方法可以调用过去,但是唯独js的alert方法调用没有效果,所以这里采用了输出到div的形式,并增加了一个clear按钮

WKWebView不支持nib文件,所以这里需要使用代码初始化并加载WebView

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. 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端:

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

OC与JS交互之WKWebView的更多相关文章

  1. iOS(UIWebView 和WKWebView)OC与JS交互 之二

    在iOS应用的开发过程中,我们经常会使用到WebView,当我们对WebView进行操作的时候,有时会需要进行源生的操作.那么我记下来就与大家分享一下OC与JS交互. 首先先说第一种方法,并没有牵扯O ...

  2. OC与JS交互之WebViewJavascriptBridge

    上一篇文章介绍了通过UIWebView实现了OC与JS交互的可能性及实现的原理,并且简单的实现了一个小的示例DEMO,当然也有一部分遗留问题,使用原生实现过程比较繁琐,代码难以维护.这篇文章主要介绍下 ...

  3. OC和JS交互的三种方法

    看简书上说一共有六种OC和JS交互的方法,但是前三种原理都一致,都是通过检测.拦截Url地址实现互相调用的.剩下的react native等第三方框架原理不一样,也没有去研究,下边记录我使用的三种方法 ...

  4. Mac Webview OC与JS交互实现

    1.首先,需要定义一个JS可识别的变量(如external)用于OC与JS交互 - (void)webView:(WebView *)sender didClearWindowObject:(WebS ...

  5. OC与JS交互之UIWebView

    随着H5的强大,hybrid app已经成为当前互联网的大方向,单纯的native app和web app在某些方面显得就很劣势.关于H5的发展史,这里有一篇文章推荐给大家,今天我们来学习最基础的基于 ...

  6. OC与JS交互前言

    OC与JS交互过程中,可能会需要使用本地image资源及html,css,js文件,这些资源应该如何被加载? 一.WebView加载HTML UIWebView提供了三个方法来加载html资源 1.  ...

  7. iOS(WKWebView)OC与JS交互 之三

      随着H5功能愈发的强大,没进行过混合开发的小伙们都不好意思说自己能够独立进行iOS的app开发,在iOS7操作系统下,常用的native,js交互框架有easy-js,WebViewJavascr ...

  8. iOS WKWebView OC 与 JS 交互学习

    我写WKWebView 想让 服务端相应 一个 方法但是不响应,根据 UIWebView 用 JSContext就能拿到响应的处理经验是不是服务端 也需要 对 WKwebView有兼容的一个写法??? ...

  9. OC与JS交互之JavaScriptCore

    JavaScriptCore提供了JavaScript和Objective-C桥接的Obj-C API.JavaScriptCore提供了让我们脱离UIWebView执行JavaScript脚本的能力 ...

随机推荐

  1. 【OCP|052】OCP最新题库解析系列-2

    2.Which two are true about Optimizer Statistics? ❑ A) They do not persist across Instance restarts. ...

  2. (转)Javascript模块化编程(二):AMD规范

    转自 ruanyifeng 系列目录: Javascript模块化编程(一):模块的写法 Javascript模块化编程(二):AMD规范 Javascript模块化编程(三):Require.js的 ...

  3. windows10 pip install MySQL-python mysqlclient

    https://dev.mysql.com/downloads/connector/python/ 到上述地址下载对应系统的驱动程序安装即可. 安装mysqlclient方法如下: https://w ...

  4. sourceTree"重置提交"和"提交回滚"的区别

    相信用过sourceTree的伙伴们都认识这两,但是不一定用过这两个功能,甚至是不能很好的把握它两的区别,根据自己最近亲身测试,总算是能小小的总结一下了 首先这儿假如,历史版本已经出现了1.2.3.4 ...

  5. mybatis的mapper.xml使用parameterType使用的报错

    错误在于一个写的get(Long id)的查询方法, 而在Mapper.xml中我定义了这个接收的参数的类型是int类型, 结果就报了如下的错误 org.mybatis.spring.MyBatisS ...

  6. Java线程池的选择

    在java的concurrent.Executors主要提供两种线程池:无固定线程数但有限制任务队列的cachedThreadPool与有固定线程数但无任务队列限制的fixedThreadPool,这 ...

  7. 10. JavaScript学习笔记——JSON

    10. JSON ///[JSON是一种数据格式,不是JS 独有的] ///[JSON语法] /* 1.数据书写格式:"name":value,JSON要求给属性名加上[双引号], ...

  8. Smarty <= 3.1.32 Remote Code execution(CVE-2017-1000480)

    Smarty介绍   smarty是一个php模板引擎,其项目地址:https://github.com/smarty-php/smarty 测试环境搭建   下载:https://github.co ...

  9. iterm自动登录ssh脚本

    经常在工作中需要切换到不同的服务器去部署,或者查看日志,每次登录都要去找对应的IP和地址,非常麻烦,最终决定使用iterm2+脚本来实现自动登录. 1.iterm2(下载安装不再介绍http://ww ...

  10. (转)OpenStack之服务端口号

    原文:https://blog.csdn.net/henulwj/article/details/47276391 在部署openstack的过程中,你会遇到配置各种服务的endpoint,opens ...