iOS开发中Cordoval运用技巧分析
ios开发中cordoval运用技巧分析。
一:关于cordoval理论知识
1:phonegap是手机平台上流行的一款中间件。它构建在各种手机平台所提供的webview(内核)的基础之上,使用javascript语言对应用开发者提供统一的接口(如调用相机、调用其他本地组件),从而屏蔽了各手机平台上os的异构。在无线小组的调研任务中,我的任务主要是负责ios平台上的调研,本文简单描述了ios平台上phonegap与平台本地的互操作性的实现。
2:phonegap因为被捐赠给了apache而改名为cordova,所以phonegap里的类名都以cdv作为前缀。在ios平台上,最重要的一个核心类是cdvviewcontroller。该类直接继承自uiviewcontroller,因而具备了所有uiviewcontroller所具备的特性。同时,该类还实现了两个protocol(即接口):uiwebviewdelegate和cdvcommanddelegate。因此它也负责uiwebview的一些callback,以及cdvinvokedurlcommand的执行。
3:cdvviewcontroller类的主要对象成员是cdvcordovaview *webview,在源代码中可以看出,这个webview对象是cdvviewcontroller的self.view上的唯一被add进来的子对象,即负责了整个cdvviewcontroller类的显示。而cdvcordovaview类则没什么特别的,它直接继承自uiwebview。
4:当cdvviewcontroller在构建时,它有两个很重要的属性:nsstring*wwwfoldername和nsstring *startpage。这两个属性值使得cdvviewcontroller在load之后直接加载wwwfoldername下的startpage作为初始显示的页面。
以上是对cdvviewcontroller的一个简单介绍。容易明白的是,在ios应用中使用了cdvviewcontroller之后,界面实际上就完全交给了cdvcordovaview*webview,即一个uiwebview。
二:使用cordoval常碰到的问题
config.xml 是一个用来配置应用的全局属性的文件, 在此文件中配置的属性应该是能适应所有平台的. 在编译的时候配置文件将会被编译到对应的平台中.
1:如何在cordoval加载远程的url网址
在config.xml配置文件时增加下面两个,便可以打开url的html页面
2:在cordoval中加载同一个域的url是在app打开,跳转到其它却是用safari浏览器打开
同样是在config.xml配置中把下面两个删除,这样它便会一直在app里面进行跳转
--> -->
2.1:禁用 webviewbounce
uiwebview是ios sdk中一个最常用的控件, 在cordova中, 默认也是使用uiwebview作为默认视图显示我们的html应用的.
在使用cordova的项目中, 默认webviewbounce这个选项是打开的, 所以使用手指向下或者向上滑动屏幕时, 经常会看到页面底部和屏幕底部会出现一大片空白, 然后松开手指后, 再弹回去的特效.
2.2:config.xml access配置
只允许google.com access to google.com:
只允许google.com的https协议 access to the secure google.com (https://):
二级域名(maps) access to the subdomain maps.google.com:
所有二级域名 access to all the subdomains on google.com, for example mail.google.com and docs.google.com:
所有域名 access to all domains, for example, google.com and developer.mozilla.org:
2.3:config.xml navigation whitelist
说明:webview可以跳转至的url
2.4:config.xml intent whitelist
说明:可以打开的链接
2.5:config.xml network request whitelist
说明:网络请求(如xhr等)白名单
2.6:index.html content security policy
说明:页面上的资源白名单
主要分这几类:default-src,style-src,script-src,img-src,font-src,media-src 等
参数值可以是:*,'self','unsafe-inline',data: 等
我使用的是非常宽松的策略:
允许所有域名的数据,允许不安全的内联,允许data:(主要用于base64形式的图片,字体等)
3:如何加载不同的启动页url地址
在配置config.xml文件中有个content的节点,里面默认是有一个打开本地的地址index.html(比如:
);这个就是跳转到本地包里面的html页面,也可以修改成(比如: ); 上面这种只是修改默认的地址,可能不符合对于项目实际用法,项目中要加载cordova都会有一个viewcontroller的控制器继承于cdvviewcontroller,它时就有一个属性startpage用于设置跳到webview加载的html页面;其中使用cdvviewcontroller通常需要设置wwwfoldername的目录名称,和startpage首页的名称即可。默认wwwfoldername为www,startpage默认为index.html;这个也是模板直接生成时文件的名称;
self.viewcontroller.startpage=@"http://www.cnblogs.com";
4:如何加载html页面存放在盒沙中
self.viewcontroller = [[mainviewcontroller alloc] init]; nsstring *curfilepath=[nsstring stringwithformat:@"file://%@/www",[nssearchpathfordirectoriesindomains(nsdocumentdirectory, nsuserdomainmask, yes) objectatindex:0]]; nslog(@"路径为:%@",curfilepath); if ([[nsfilemanager defaultmanager] fileexistsatpath:curfilepath]) { self.viewcontroller.wwwfoldername = curfilepath; } self.viewcontroller.startpage=@"index.html";同样是在wwwfoldername上做文章,因为它是前缀文件夹的路径,这边要注意是关于路径要运用file://方式进行读取;
因为可以读取沙盒里面的html页面,这样我们就可以更加灵活运用,比如html通过服务端去下载到沙盒解压,这样就可以做到动态修改;
5:加载页面跟结束加载页面的监听,有两个通知可以监听,用来处理等待效果展现
- (void)viewdidload { [super viewdidload]; // do any additional setup after loading the view from its nib. nsnotificationcenter *center = [nsnotificationcenter defaultcenter]; [center addobserver:self selector:@selector(onnotification:) name:cdvpluginresetnotification // 开始加载 object:nil]; [center addobserver:self selector:@selector(onnotificationed:) name:cdvpagedidloadnotification // 加载完成 object:nil]; } - (void)onnotification:(nsnotification *)text{ nslog(@"-----开始等待------"); } - (void)onnotificationed:(nsnotification *)text{ nslog(@"-----结束等待------"); }6:刷新uiwebview,uiwebview直接更改url并reload是没有用的。必须声明一个nsurlrequest,并重新loadrequest。刷新时的url必须是符合cordova规则的url。在cordova中有一个appurl的方法,通过这个方法转出的url才能被cdvviewcontroller正常加载;
localwebvc.wwwfoldername = @"www"; localwebvc.startpage = @"local.html"; nsurl *url = [self.localwebvc performselector:@selector(appurl)]; if (url) { nsurlrequest *request = [[nsurlrequest alloc] initwithurl:url]; [self.localwebvc.webview loadrequest:request]; }7:使用pod管理cordoval及其插件(ios8以上才可以使用到最新版本)
pod 'cordova'如果需要引入一些相关的插件,可以加入如下配置,下面的这些插件可以通过pod搜索到:
pod 'cordovaplugin-console' pod 'cordova-plugin-camera' pod 'cordova-plugin-contacts' pod 'cordova-plugin-device' pod 'cordova-plugin-device-orientation' pod 'cordova-plugin-device-motion' pod 'cordova-plugin-globalization' pod 'cordova-plugin-geolocation' pod 'cordova-plugin-file' pod 'cordova-plugin-media-capture' pod 'cordova-plugin-network-information' pod 'cordova-plugin-splashscreen' pod 'cordova-plugin-inappbrowser' pod 'cordova-plugin-file-transfer' pod 'cordova-plugin-statusbar' pod 'cordova-plugin-vibration'注意:如果没有用pod来管理cordova,默认工程都会有一个cordovalib.xcodeproj来把cordova的类引入,所以建议cordova用pod引入,就可以调用,而关于html、js等静态模板还是在工程中;可以查看下面两个网址
ios中cordova开发初探 地址:
cordova使用pod实例 地址:【pod引入的模块都存在】
三:插件内容
对于cordova在插件上面还是比较多,也可以自定义插件的开发,对于插件下面已经有列出一些,其它插件可以上cordova或者github进行查找;
支付宝支付插件: ios/android 地址:https://github.com/fami2u/cordova-plugin-alipay.git 微信支付插件: ios/android 地址:https://github.com/fami2u/cordova-plugin-weipay.git ping++支付插件: ios 地址:https://github.com/fami2u/cordova-ping-fami.git 扫描二维码和条形码插件: ios/android 地址:https://github.com/fami2u/cordova-barcodescanner-fami.git 拍照插件: ios/android 地址:https://github.com/fami2u/cordova-plugin-camera.git 极光推送插件: ios/android 地址:https://github.com/fami2u/jpush-phonegap-plugin.git ios 地址:https://github.com/fami2u/cordova-jpush-fami.git 第三方登录插件: ios 地址:https://github.com/fami2u/cordova-umlogin-fami.git js 地址:https://github.com/fami2u/cordova-plugin-wechat.git 第三方分享插件: ios 地址:https://github.com/fami2u/cordova-umshare-fami.git 跳转地图插件: ios 地址:https://github.com/fami2u/cordova-plugin-map.git 视频播放插件: ios 地址:https://github.com/fami2u/cordova-player-fami.git
四:有可能出现的问题
1:在使用cordova6.0的过程中,编译好的app运行在ios7+系统上默认是与状态栏重叠的,而运行在ios6及老版本中时是于状态栏分离的。
解决办法:把文件mainviewcontroller.m中的方法viewwillappear进行相关修改如下。作用是更改view的边界,使其下移20px,刚好是状态栏的高度。
- (void)viewwillappear:(bool)animated { if([[[uidevice currentdevice]systemversion ] floatvalue]>=7) { cgrect viewbounds=[self.webview bounds]; viewbounds.origin.y=20; viewbounds.size.height=viewbounds.size.height-20; self.webview.frame=viewbounds; } [super viewwillappear:animated]; }2:在html页面内调用系统相机以后再返回,整个页面底部会有白色的空白控件,用调试工具查看后空白区域的高度是20px.该如何解决?
解决办法:由于整个cordova项目相当于一个页面的应用,不同的模块聚集在一起,所以当当前屏幕消失后(比如进入系统相机拍照页面)再出现的时候,还是会执行上面的代码,所以界面高度再次减少20px.
-(void)viewwilldisappear:(bool)animated { if([[[uidevice currentdevice]systemversion ] floatvalue]>=7) { cgrect viewbounds=[self.webview bounds]; viewbounds.origin.y=20; viewbounds.size.height=viewbounds.size.height+20; self.webview.frame=viewbounds; } [super viewwilldisappear:animated]; }五:不错的使用总结:
六:js跟oc交互实例
1:因为cordoval要跟js交互都是要利用cdvplugin进行
#import #import @interface cdvhelloworld : cdvplugin -(void)sayhello:(cdvinvokedurlcommand *)command; @end所以我们创建一个插件类,继承于cdvplugin类,其中cdvinvokedurlcommand就是用于交互的类;
#import "cdvhelloworld.h" @implementation cdvhelloworld -(void)sayhello:(cdvinvokedurlcommand *)command { //接收js传过来的值 nsdictionary *options=[command argumentatindex:0 withdefault:nil]; //对应键名 nsstring *curvalue=options[@"quality"]; uialertview *myalertview=[[uialertview alloc]initwithtitle:@"我是小实例" message:[nsstring stringwithformat:@"当前的内容从js传过来的值为:%@",curvalue] delegate:self cancelbuttontitle:@"取消" otherbuttontitles:@"确定", nil]; [myalertview show]; //数据回调 if ([curvalue isequaltostring:@"200"]) { curvalue=@"201"; } cdvpluginresult *pluginresult=[cdvpluginresult resultwithstatus:cdvcommandstatus_ok messageasstring:@"oc回调过来的值"]; [self.commanddelegate sendpluginresult:pluginresult callbackid:command.callbackid]; } @end上面的实例有接收js传过来的值,也有再回调给js的值,回调时要利用self.commanddelegate;其中cdvpluginresult里面包括很多状态,上面只是把正确的状态赋值传回去,而messageasstring只是会字符串,还有其它类型的,比较字典、数组等;
2:config.xml修改配置,注册刚才我们注册的这个插件,给它定义一个helloworld的名字,value则是我们刚才创建的类名
3:html跟js的代码,sayhello则是我们类中的一个方法名,helloworld则是我们在配置中的那个名字,可以对它进行传参;
<title></title> <script type="text/javascript" charset="utf-8" src="cordova.js"></script><script type="text/javascript" charset="utf-8"> //简单跟oc交互,没有回调 //function test() //{ // options={quality:"200"}; // cordova.exec(null,null,'helloworld','sayhello',[options]); //} function test() { options={quality:"200"}; cordova.exec( function(result){ var s=result; alert(s); }, function(error) { alert("error",error); } ,'helloworld','sayhello',[options]); } </script><button onclick="test();">交互oc</button>
上一篇: 简单了解Python hashlib模块
下一篇: linux服务中开启防火墙的两种方式