WKWebView-b

摘要:
在上一篇文章中,我们使用JavaScriptCore框架重写了前面的示例。iOS8苹果更喜欢HTML5,并重新构建了UIWebVIew,这为我们带来了WKWebView,大大提高了其性能、稳定性和功能性,并更好地支持HTML5的新功能。WKBackForwardListItem:webview中后退列表中的网页。WKNavigationResponse:包含可能导致网页导航更改的返回内容信息,用于确定是否进行导航更改。WKWebViewConfiguration:初始化Web视图设置。WKWebsiteDataStore:包含网页数据存储和搜索。回到前两个,WKWebView中的三个代理方法。1.WKNavigationDelegate代理提供的方法可用于跟踪加载过程并决定是否执行跳转。

上一篇文章我们使用了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》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇js运算符!【转】EVC /PB /WinCE开发问题下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

AFNetworking的详细解析

AFNetworking serializer 分析 AFNetworkResponse.png 1. AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 所有的网络请求,均有manager发起 2. 需要注意的是,默认提交...

Android开发中java与javascript交互:PhoneGap插件vs addJavascriptInterface

1.前言 在《用PhoneGap+jQueryMobile开发Android应用实例》中,我们讲到PhoneGap(以下称Cordova)开发环境的搭建,以及如何整合出一个基本的Android应用框架(并给出了范例代码)。于是乎,我们便开始日夜兼程,披星戴月的炮制我们的第一个手机应用了。 但实际上,除了常见的API调用规范(有且仅有自查手册一途)引起的问题...

NSDictionary读取数据类型异常问题.

起因:做网络交互时,经常会使用JSON作为数据的承载体,本来是件好事,但是用多了,发现iOS侧偶尔会出现异常,几经比较发现是服务器给的数据有问题,该给INT的给按照STR给了,服务器能做动态更新,可客户端不行啊,怎么办?NSDictionary读到的是id类型,如果是数字,需要再转换下才可以,出问题就在这里.那解决思路就在这里,在这里增加判断实现用到了以下...

android 用webView作为编辑器 各种问题

1.首先我要说明一下为什么要写这个博客,因为公司最近需要一个自定义的编辑器,苦于没有思路在网上找了好久,看到了好多android实现的编辑器(其实也就那么几个并不多),公司需求和网页端同步共享创建的文档,需要用到html保存数据,然后我就被迫开始了编辑器之旅,这东西我觉得最大的难点就是要手机和网页端保持一致,手机并没有那么自由统一起来还是非常困难的,接下来...

iOS WKWebView

Webkit 是 iOS 8.0 后提供的新的框架,组件WKWebView比较UIWebView 速度更快、占用内存更少了,可支持性更多 WKWebView可通过KVO监听属性 title、estimaredProgress、hasOnlySecureContent estimatedProgress: 当前navigation加载的进度,加载进度包括主要...

前端webview开发中遇到的一些问题及其解决方法

最近做了一个webview中的兑换页面,本来以为很简单,想不到遇到了远远超出预期数量的BUG,记下来,以备后患。 1 inline-block元素折行   BUG描述:现在我有三个DIV,要在一列等宽排列,设定宽度为33.33333%,想象中应该是正好充满一列。 然而事实是,div折行了=。=,div之间还出现了一个缝隙。 这个问题很常见,出现的原因是浏...