[心得] phoneGap,doctor总结。重点是如何让页面自动跳转到settings bundle中用户设置的网址
这次phoneGap的开发,了却了我一直以来想学学这方面知识的心愿——这算是hybrid程序员的起点。之前一直认为很神秘,接触起来也觉得并不很难学,充分证明人类对于“未知的恐惧”的心理作用,通过越来越多的经历,会变得不那么严重。当然,如果要研究到一定的深度,也不会很容易。
doctor项目,并不能算是真正意义上的phoneGap开发,它只是使用了phoneGap框架,几乎没有用到其中的亮点——对于移动设备硬件资源的调动、用js代码与oc代码进行互动等。虽然如此,仍然出现了很多我没接触的东西,需要总结一下。
1. 使用iframe开发网页的通用部分,还是很不错的选择。因为通用部分完全就是一个页面,维护起来非常方便。与之前开发的项目相比,虽然维护通用类也挺方便的,但是iframe还是更上一层楼。其次,跳转行为不会导致主frame的刷新屏幕动作,这个在体验度上算是一个不小的优化。在兼容方面,还存在一些问题,有兴趣的可以去baidu一下,很多解决方案。
2. iScroll的滚动效果类库。很简单很直观,模拟了在移动设备上那种有惯性的滚动效果,触发了3d硬件加速,所以性能没问题。其他功能包括下拉刷新等等,在我之前的博客中转载过使用方法。http://www.cnblogs.com/GeekHacker/archive/2012/06/24/2560065.html
3. JQmobi移动版的开发工具类库,由于体积小,所以删掉了一些常见的操作,比如,在我用的时候就发现没有click()的方法,还是需要用原生的onclick去绑定。以后真正频繁使用的时候,需要去看一下api手册了。jQMobi API 函数(中英文对照)
4. ASP工作原理,在服务器端执行的类似js功能的语句。用户请求一个页面时,如果服务器发现请求的是html文件,就会毫不犹豫的返回给你。如果发现是aspx文件,那么就会在服务器端,按照代码捆绑数据,并生成相应的布局,然后生成一个html文件,再返回给客户端。估计php也是这样的。通过修改项目的aspx页面,前端-后台-数据库之间的关系在我脑子中终于不那么模糊了。算是没有白白的蛋疼。。。
5. sarfari很好的支持html5,所以日后在这种项目上,要尽量将编程思路改成html5模式,移动平台开发,是练手html5的绝佳场所。
6. 老师提出要求,需要在iphone的设置里,让用户可以设置一个网址,然后,当开启doctor应用的时候,要自动的跳转到该网址去请求aspx的站点。
首先,跳转我使用的是<meta http-equiv="refresh"content="2;'http://www.baidu.com'">,其中baidu地址是测试用,其实这里未来应该是用户设置的。
oc中,用户设置的那个功能需要引入settings bundle文件来控制,所以这就出现一个问题,我用oc代码去读取用户的设置,怎么把读取到的数据写到html文件里呢?!
这个问题,我请教了季万强大神——此人各种编程语言好像都很懂。。。他告诉我一个思路,就是将你这个跳转页所有代码转成NSString(oc中的字符串对象),然后使用操作字符串的方法,找出其中目标字段,将这个字段,再用替换字符串的方法,替换成你读取到的用户设置,最后,再将这个NSString写成一个新的html文件。这个新的html文件将成为你加载使用的页面。下面贴上代码,以后复用。(settings bundle的基本用法就不说了,很多地方有相关文章)
在AppDelegate.m中找到- (BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions方法,显而易见,这里的代码就是在控制phoneGap程序启动后如何加载起始页。所以,在所有这些默认代码的前面,开始书写我们的代码,因为我就是要起始页就具有跳转的功能。
// 加载默认配置
NSUserDefaults *defaults = [NSUserDefaultsstandardUserDefaults];
NSString *ip = [defaults stringForKey:@"ipaddress"]; //ipaddress是我在settings bundle中设置的key值,对应的就是用户设置的网址
if(!ip) { //如果前面的方法取不到数据,就再用下面这个方法取。
[self performSelector:@selector(registerDefaultsFromSettingsBundle)];
ip = [[NSUserDefaultsstandardUserDefaults] stringForKey:@"ipaddress"];
}
附加:registerDefaultsFromSettingsBundle这个方法也是自定义的,所以这里要先去实现这个方法,代码如下:
- (void)registerDefaultsFromSettingsBundle
{
NSString *settingsBundle = [[NSBundlemainBundle] pathForResource:@"Settings"ofType:@"bundle"];
if(!settingsBundle) {
NSLog(@"Could not find Settings.bundle");
return;
}
NSDictionary *settings = [NSDictionarydictionaryWithContentsOfFile:[settingsBundle stringByAppendingPathComponent:@"Root.plist"]];
NSArray *preferences = [settings objectForKey:@"PreferenceSpecifiers"];
NSMutableDictionary *defaultsToRegister = [[NSMutableDictionaryalloc] initWithCapacity:[preferences count]];
for(NSDictionary *prefSpecification in preferences) {
NSString *key = [prefSpecification objectForKey:@"Key"];
if(key) {
[defaultsToRegister setObject:[prefSpecification objectForKey:@"DefaultValue"] forKey:key];
}
}
[[NSUserDefaultsstandardUserDefaults] registerDefaults:defaultsToRegister];
}
到这里,我们已经取到了用户的设置,保存在了字符串变量ip中。下面就是对页面代码进行操作。这里我们需要先将模板中的http://www.baidu.com改成一个我们自定义的标示代码,我改的是ibokanzhangcong,也就是说<meta http-equiv="refresh"content="2;'ibokanzhangcong'">,未来我做替换的时候,就是将ibokanzhangcong字符串替换成读取到的用户设置ip。
我要把我要改的页面文件复制一个副本,例如,我要改的是login.html中的<meta>,那么我就复制一个,并且起名为login_temp.html文件,这将成为代码模板,作为每次修改的原始样本,不做任何修改,也不加载。如果不这样做,而是直接重写模板文件的话,就崩溃。因为你覆盖了原先这个文件,你就找不到ibokanzhangcong这个标示了,你运行了一次之后,这个标示就已经被替换为用户设置的ip了,那你下次再改的时候,就找不到标示了。
//将页面文件读取为nsstring
NSString *htmlfile = [[[NSBundlemainBundle] bundlePath] stringByAppendingFormat:@"/www/doctorsvn2/login.html"]; //这是模板login的路径
NSString *htmlTempFile = [[[NSBundlemainBundle] bundlePath] stringByAppendingFormat:@"/www/doctorsvn2/login_temp.html"]; //这是被设置后的login_temp.html的路径
NSMutableString *htmlstr = [NSMutableStringstringWithContentsOfFile:htmlTempFile encoding:NSUTF8StringEncodingerror:nil]; //按照模板转成字符串
//将文件中的地址替换成用户设置的网页地址
NSString *modifyStr = [htmlstr stringByReplacingOccurrencesOfString:@"ibokanzhangcong"withString:ip]; //字符串替换,构建新的字符串
if([modifyStr writeToFile:htmlfile atomically:YESencoding:NSUTF8StringEncodingerror:nil]) { //将改好的字符串,再写成html文件
NSLog(@"write good");
};
这样就实现了用户的设置。那么,到底是什么原理呢?关键的一步就是将html文件代码变成一个很长的字符串变量,然后对他进行修改,最后再转成一个html文件。需要突出强调的是,创建login.html的副本login_temp.html这一步,思路就是,转成字符串的时候,是读取login_temp.html文件,替换完之后写文件的时候,是写成login.html文件名,也就是,login_temp.html的代码永远不会改变,作为模板源文件使用,而login.html则是每次重写都会被覆盖成新的。