2寸220Ⅴ2l 220 25f法兰电磁阀阀多少

前一篇文章已经介绍了JS与iOS交互,用UIWebView实现的方法。需要了解相关知识,请查看前一篇博客。地址:JS交互的方法(上)UIWebView这里我们来介绍另外一种基于iOS8新推出的WKWebView组件实现的方法。WKWebView实际上就是一个新的、高性能的WebView 解决方案。下面我们就来看看如何利用WKWebView实现混合开发框架。先看看实现效果:说明:本文我们只讨论如何实现iOS与JS的交互,由于不精通HTML,所以小Demo可能会有小瑕疵,大神莫怪。1. 配置偏好设置[code]
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
// 设置偏好设置
config.preferences = [[WKPreferences alloc] init];
// 默认为0
config.preferences.minimumFontSize = 10;
// 默认认为YES
config.preferences.javaScriptEnabled = YES;
// 在iOS上默认为NO,表示不能自动通过窗口打开
config.preferences.javaScriptCanOpenWindowsAutomatically = NO;2. 配置JS与iOS的交互内容WKUserContentController是用于给JS注入对象的,注入对象后,JS端就可以使用。直白点说就是给JS与iOS的交互提供一个通道,以后JS与iOS交互就是通过这个AppModel值识别和传值的,传数据统一通过body传,可以是多种类型,只支持NSNumber, NSString, NSDate, NSArray,NSDictionary, and NSNull类型。[code]
// 通过JS与webview内容交互
config.userContentController = [[WKUserContentController alloc] init];
// 注入JS对象名称AppModel,当JS通过AppModel来调用时,
// 我们可以在WKScriptMessageHandler代理中接收到
[config.userContentController addScriptMessageHandler:self name:@"AppModel"];下图是HTML中想iOS发送消息的代码,从这句代码我们就能看出AppModel值得作用3. 加载网页[code]
//通过默认的构造器来创建对象
self.webView = [[WKWebView alloc] initWithFrame:self.view.boundsconfiguration:config];
NSURL *path = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"html"];
[self.webView loadRequest:[NSURLRequest requestWithURL:path]];
[self.view addSubview:self.webView];4. 加载网页时调用的代理方法完成以上配置以后我们就按照程序的执行顺序解析代码,这里我们以点击提示弹窗为例进行分析,其他几个功能里也有一些需要注意的点就需要大家自己思考了。在HTML中添加点击事件
点击事件为HTML代码,不做详述。实现点击事件,这个方法会调用iOS中的方法把body值传过去[code]function callJsAlert() {//在JS端调用alert函数时,会触发代理方法一,括号中的内容会传到此代理方法中alert('这个是OC调用JS的方法,并且通过Alert()进行显示出来!'); //在JS端调用postMessage函数时,会触发代理方法二,body的内容会传过去window.webkit.messageHandlers.AppModel.postMessage({body: '在JS中调用JS中方法'});}运行程序后,触发点击事件前会依次执行以下几个代理方法,我们逐一分析下[code]/** 代理方法三: 请求开始前,会先调用此代理方法,与UIWebView的 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationT 方法类似,此方法在上篇博客中分析过 */- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSString *hostname = navigationAction.request.URL.host.lowercaseS
if (navigationAction.navigationType == WKNavigationTypeLinkActivated&& ![hostname containsString:@"."]) {// 对于跨域,需要手动跳转 [[UIApplication sharedApplication] openURL:navigationAction.request.URL]; // 不允许web内跳转 decisionHandler(WKNavigationActionPolicyCancel);
} else { self.progressView.alpha = 1.0; decisionHandler(WKNavigationActionPolicyAllow);
} NSLog(@"00===%s", __FUNCTION__);}decisionHandler(WKNavigationActionPolicyAllow)的作用是设置能否跳转,WKNavigationActionPolicyAllow是一个枚举值表示允许调转,WKNavigationActionPolicyCancel表示不允许跳转。[code]/** 代理方法四 开始导航跳转时会回调 */- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation { NSLog(@"22===%s", __FUNCTION__);}[code]/** 代理方法五: 在响应完成时,会回调此方法如果设置为不允许响应,web内容就不会传过来 */- (void)webView:(WKWebView *)webViewdecidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponsedecisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
decisionHandler(WKNavigationResponsePolicyAllow);
NSLog(@"11===%s", __FUNCTION__);}[code]/** 代理方法六: 页面内容到达main frame时回调 */- (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation { NSLog(@"55===%s", __FUNCTION__);}[code]/** 代理方法七: 导航完成时,会回调(也就是页面载入完成了) */- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation { NSLog(@"66===%s", __FUNCTION__);}这个代理方法执行完成,网页才完整的加载出来,还有一些代理方法是在页面加载异常时调用的,我们这里统一来看一下。[code]// 接收到重定向时会回调- (void)webView:(WKWebView *)webViewdidReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation { NSLog(@"33===%s", __FUNCTION__);}// 导航失败时会回调- (void)webView:(WKWebView *)webViewdidFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error { NSLog(@"44===%s", __FUNCTION__);} // 导航失败时会回调- (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {
NSLog(@"77===%s", __FUNCTION__);}// 9.0才能使用,web内容处理中断时会触发- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView { NSLog(@"99===%s", __FUNCTION__);}//关闭网页时调用- (void)webViewDidClose:(WKWebView *)webView {
NSLog(@"99===%s", __FUNCTION__);}5. 触发点击事件时调用的代理方法触发点击事件,即执行如下HTML代码[code]//提示弹窗alert('这个是OC调用JS的方法,并且通过Alert()进行显示出来!');//确认弹窗if (confirm('confirm', 'Objective-C call js to show confirm')) { document.getElementById('jsParamFuncSpan').innerHTML = 'true';
} else { document.getElementById('jsParamFuncSpan').innerHTML = 'false';
//输入弹窗 var response = prompt('Hello', '请输入你的名字:'); document.getElementById('jsParamFuncSpan').innerHTML =执行上述代码后,iOS会执行下面的代理方法调用这几个代理方法后,iOS会执行相应的弹窗操作。[code]/** 代理方法一 */// 在JS端调用alert函数时,会触发此代理方法。// JS端调用alert时所传的数据可以通过message拿到// 在原生得到结果后,需要回调JS,是通过completionHandler回调- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)messageinitiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
NSLog(@"100===%s", __FUNCTION__);
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"alert" message:@"JS调用alert"
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { completionHandler();
[self presentViewController:alert animated:YES completion:NULL];
NSLog(@"------&%@", message);}// JS端调用confirm函数时,会触发此方法// 通过message可以拿到JS端所传的数据// 在iOS端显示原生alert得到YES/NO后// 通过completionHandler回调给JS端- (void)webView:(WKWebView *)webViewrunJavaScriptConfirmPanelWithMessage:(NSString *)messageinitiatedByFrame:(WKFrameInfo *)framecompletionHandler:(void (^)(BOOL result))completionHandler {
NSLog(@"101===%s", __FUNCTION__);
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"confirm" message:@"JS调用confirm" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action){ completionHandler(YES);
[alert addAction:[UIAlertAction actionWithTitle:@"取消"
style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { completionHandler(NO);
[self presentViewController:alert animated:YES completion:NULL];
NSLog(@"%@", message);}// JS端调用prompt函数时,会触发此方法// 要求输入一段文本// 在原生输入得到文本内容后,通过completionHandler回调给JS- (void)webView:(WKWebView *)webViewrunJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultTextinitiatedByFrame:(WKFrameInfo *)framecompletionHandler:(void (^)(NSString * __nullable result))completionHandler {
NSLog(@"102===%s", __FUNCTION__);
NSLog(@"%@", prompt);
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"textinput" message:@"JS调用输入框"preferredStyle:UIAlertControllerStyleAlert];
[alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { textField.textColor = [UIColor redColor];
[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { completionHandler([[alert.textFields lastObject] text]);
[self presentViewController:alert animated:YES completion:NULL];}6. 执行跳转控制器的代理方法HTML代码中执行如下代码会调用iOS中的代理方法[code]// AppModel是我们所注入的对象window.webkit.messageHandlers.AppModel.postMessage({body: response});执行上述代码会调用如下代理方法[code]/** 代理方法二 */- (void)userContentController:(WKUserContentController *)userContentControllerdidReceiveScriptMessage:(WKScriptMessage *)message {
if ([message.name isEqualToString:@"AppModel"]) { // 打印所传过来的参数,只支持NSNumber, NSString, NSDate, NSArray, // NSDictionary, and NSNull类型 NSLog(@"9999===%@", message.body);
//跳转到指定控制器中JumpViewController *root = [[JumpViewController alloc]init];root.str = message.[self.navigationController pushViewController:root animated:YES];
}}到这里终于实现了控制器的跳转7. 其他在加载网页时往往还会用KVO监听是否正在加载、当前进度等状态,这里不再赘述。8. 详细代码请下载源码自行研究地址:http://download.csdn.net/detail/qq_3494
最新教程周点击榜
微信扫一扫一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!
二、互相尊重,对自己的言论和行为负责。
本文标题:
本页链接:5093人阅读
转载自:&/p/90a90bd13aac
UIWebView 之痛
开发App的过程中,常常会遇到在App内部加载网页,通常用UIWebView加载。而这个自iOS2.0开始使用的Web容器一直是开发的心病:加载速度慢,占用内存多,优化困难。如果加载网页多,还可能因为过量占用内存而给系统kill掉。各种优化的方法效果也不那么明显,常见的优化缓存方式:
1、尽量使用 GET 请求,iOS 系统 SDK 会自动帮你做缓存。你需要的仅仅是设置下内存缓存大小、磁盘缓存大小、以及缓存路径。只要设置了这两行代码,基本就可满足80%的缓存需求。
设置缓存.jpg
2、Web资源离线加载,热更新资源,完成另外20%的缓存需求(Hybrid框架的Web部分)。
可是无数开发者尝试自己做一个“简陋而脆弱的”系统来实现网络缓存的功能,效果往往是事倍功半 。
初识 WKWebView
UIWebView从 iOS2 就有,iOS8 以后,苹果推出了新框架 WebKit,提供了替换 UIWebView 的组件 WKWebView。各种 UIWebView 的性能问题没有了,速度更快了,占用内存少了,体验更好了,下面列举一些其它的优势:
1、在性能、稳定性、功能方面有很大提升(加载速度,内存的提升谁用谁知道)
2、更多的支持 HTML5 的特性
3、官方宣称的高达60fps的滚动刷新率以及内置手势
4、Safari 相同的 JavaScript 引擎
5、将 UIWebViewDelegate 与 UIWebView 拆分成了14类与3个协议,包含该更细节功能的实现。
相比之下,WKWebView 复杂得多,一些常用API如下:
WKWebView.jpg
JavaScript 配置相关
JavaScript API.jpg
存储相关(只支持iOS9以上)
存储类型.jpg
存储 API.jpg
页面加载相关
WKWebView loadRequest.jpg
WKNavigationDelegate.jpg
看完API以后,要掌握 WKWebView 并不难,难的是如何处理iOS版本碎片化兼容问题。
性能对比测试
都说提高多么多么大的性能,实测告诉你 WKWebView 的性能有多好,下面用实际项目做个对比测试:
UIWebView 首次加载
首页,耗时 0.0154584ms,内存消耗 24.1 MB
UIWebView耗时.jpg
UIWebView内存消耗.jpg
WKWebView 首次加载
首页,耗时 0.013875ms,内存消耗仅 6.4 MB
WKWebView耗时.jpg
WKWebView内存消耗.jpg
结论:加载耗时差别不大,WKWebView 的内存优化减少了几乎4倍,更重要的是,无论 WKWebView 跳转多少 Web 页面都没有内存泄漏了。WKWebView 使用和 Safari 相同的 Nitro JS 引擎性能,对HTML5性能也提升了4倍。
WKWebView 之坑
新技术的出现必然会或多或少的瑕疵,WKWebView 也不例外。
1、关于缓存
在 WKWebsiteDataStore 出现之前(iOS 9 中),WKWebView 是没有缓存,也无从清理。WKWebView 是基于 WebKit 框架的,它会忽视先前使用的网络存储 NSURLCache, NSHTTPCookieStorage, NSCredentialStorage等,它也有自己的存储空间用来存储cookie和cache,其他的网络类如NSURLConnection 是无法访问到的。 同时WKWebView发起的资源请求也是不经过NSURLProtocol的,导致无法拦截或自定义新请求。
体验过 WKWebView 的一定会遇到修改了H5页面,APP打开时却没有即时更新的问题(实在是缓存得太好了),iOS 8的时候只能增加时间戳的方式解决这个问题(调试下使用,生产环境就只能要求前端修改Cache-Controll了),如下:
时间戳更新.jpg
iOS 9以后终于可以使用 WKWebsiteDataStore 来清理缓存。后来Google一下,又发现iOS 8可以通过清理 Library 目录下的 Cookies 目录来清除缓存,于是
清除WKWebView缓存.jpg
缓存清理的坑趟过了,喜大普奔。
2、关于 Cookie
在使用 UIWebVIew 的时候我们并不关注 Cookie,因为在调用登录接口的时候无论是AFNetworking,还是其他,登录成功之后都会自动保存在
[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies 中,以后再使用也会自动去获取(这里有个 UIWebView 的坑:访问的链接越多,如不处理Cookie,它会加载越来越多的无效 Cookie 导致内容急剧增大)。但 WKWebView 的存储体系与 UIWebVIew 完全不一样,只能手动给它添加 Cookie,如下:
WKWebView设置cookie.jpg
但即便如此,Cookie 还是会偶现丢失的问题,最终只好采用每次 Web 开始加载之时判断 Cookie 是否存在,否则手动添加重新加载,如下:
WKWebView设置cookie.jpg
Cookie 获取的坑趟过了,再次喜大普奔。
3、关于跨域
WebKit框架对跨域进行了安全性检查限制,不允许跨域,比如从一个 HTTP 页对 HTTPS 发起请求是无效的(有一个界面要跳到支付宝页面去支付,死活没反应)。而系统的 Safari ,iOS 10出现的 SFSafariViewController 都是支持跨域的,因此解决办法如下:
跨域跳转.jpg
对于自身域名,还是建议全站 HTTPS 化吧(大势所趋)。
4、关于 JavaScript 交互
UIWebView 使用的 JavaScriptCore 框架,交互时为 JavaScript 运行的上下文环境 JSContext 注入对象 Bridge;WKWebView 使用的 WebKit 框架,交互时为 webkit.messageHandlers 注入对象,如下:
JavaScript注入.jpg
前端H5需要做判断两种不同注入方式带来的不同调用方式:
js调用.jpg
5、关于 NSURLProtocol 拦截
WKWebView 基于 WebKit 框架,与 UIWebView 机制不同:加载过程中所有的请求都不经过 NSURLProtocol,换句话说就是 WKWebView 无法拦截响应数据 鉴于之前大部分 Hybrid 框架的离线预加载机制都依赖于拦截功能,这意味着废掉很多程序猿们辛辛苦苦设计实现的 Hybrid 框架(内功尽失,感觉身体被掏空),再加上 WKWebView 自身的坑不少,因此很多团队都不会轻易替换掉 UIWebView。拥抱变化吧,WKWebView 迟早会取代 UIWebView 成为最佳
Web 容器(iOS 9带来的 SFSafariViewController 更是武功全废,啥都干不了,只能干瞪眼)。
那么问题来了,如何设计新的 Hybrid 框架呢?此处出门左转,点击文章开头进入公众号历史文章,查看《通用Web&Native交互协议设计方案》。
6、关于 POST 请求
中有关于这个坑的具体描述,笔者这里就不再做研究,这里只说明怎么趟过的坑:使用通用的 Web&Native 交互协议,为 Web 提供 Native POST 请求的接口+回调 CallBack 即可,参见
关于 JavaScript 交互。
7、关于本地 HTML 加载
当使用 loadRequest 来读取本地 Documents 目录的 HTML 文件时,WKWebView 是无法读取成功的,只能通iOS 9的新接口加载
load loacl html.jpg
但是在iOS9以下的版本是没提供这个便利的方法的,解决办法:先将本地 HTML 文件的数据 copy 到 tmp 目录中,然后再使用 loadRequest 来加载。但是如果在 HTML 中加入了其他资源文件,例如 js,css,image 等也必须一同 copy 到 tmp 中,这个是非常蛋疼的事情了。然而还有更蛋疼的事:iOS 8下还必须 copy 到 tmp 的 www 目录下 WKWebView 才能读取(Word天,心中千万只草泥马狂奔而过)。参见
8、关于捏合手势
很多人都喜欢使用 UIWebView 的捏合手势来进行放大和缩小,观看 Web 内容,但 WKWebView 在手机上不支持,却支持其他iOS设备(草泥马再次狂奔而过)。
不支持捏合手势.png
当时选择 WKWebView 就是为了提高性能,但是没有想到遇到这么多坑,真是我待 WKWebView 如初恋,WKWebView 虐我千百遍,兴许还有许多未知的坑,欢迎大家留言补充。谢谢支持!
文/zyl04401(简书作者)
原文链接:/p/90a90bd13aac
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:2045643次
积分:21525
积分:21525
排名:第285名
原创:413篇
转载:609篇
评论:98条
(2)(7)(7)(3)(2)(1)(2)(2)(6)(4)(3)(4)(12)(4)(17)(9)(5)(11)(7)(22)(3)(12)(38)(32)(20)(5)(17)(35)(10)(24)(15)(8)(28)(13)(11)(28)(26)(20)(43)(55)(13)(14)(25)(12)(19)(37)(64)(29)(31)(7)(30)(12)(45)(19)(17)(23)(8)(11)(36)}

我要回帖

更多关于 konan电磁阀 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信