伊书web排版解析

2012-3-3 评论(8) 分类:技术文章 Tags:

伊书是针对iOS的电子书WebApp,在web上排版不像原生APP有底层排版函数支持,限制很大,勉强实现了一些特性,在此分享。

内容左右对齐

给内容的DOM加上这个CSS属性即可:text-align:justify;
现代桌面浏览器几乎都支持,没详测。iOS5.0以上才开始支持这个属性,似乎若没有这个属性,左右对齐无解。

分页

web无法做到一页页定量渲染文字,分页需要一点hack才能做到。
我的做法是,一章的内容放在一个dom里,复制出一个一样的dom,限制显示一页范围的内容,根据页码调整显示位置。
一图声千言:

坏处是这样的形式要精确算准行高,就算字体大小不一样也要是跟正文一样的行高或是它倍数,一个算不准就会出现只显示半截文字的情况。也因为这样字体大小调整比较麻烦。

标点外挂

标点外挂是指一行中若第一个字符是标点符号,就把它移到上一行的末尾。具体实现方法是:

  1. 给所有标点加标签,就是字符串替换,把。?等替换成<b>。</b> <b>?</b>
  2. 遍历内容里的所有b标签,判断它们的位置是否在当前行的起始位置,若是则把它移到上一行末尾,具体代码:
$(".page_content b").each(function(i, b){
    if (b.offsetLeft == 0) {
        $(b).css({
            "position" : "absolute",
            "left": "256px",
            "top": b.offsetTop - lineHeight + "px"
        })
    }
});

内容缩进、信件落款左右对齐特殊处理

内容数据我是手工格式化后存到json里的,在这些特殊的地方加了标签,在显示时替换成dom按这些不同的类型给内容以不同的缩进/对齐。

注释

同上,在需要注释的地方用自定义的标签把内容包在标签里,在显示内容时把这个标签替换成dom,用js控制这个dom的touch事件显示内容就行了。需要判断这个注释的位置,以决定注释内容的显示位置。

[iOS]给UIWebView头尾插入自定义View

2012-2-25 评论(4) 分类:技术文章 Tags:

src与demo:https://github.com/bang590/iOSPlayground/tree/master/TWebview

经常有这样的需求:需要给webview头部加个自定义view,这个view不是固定的而是要跟webview一起滚动。例如iMail里的读邮件页面,头部有收件人等信息,下面是一个webview。如浏览器,顶部的地址栏要随页面滚动。如阅读类软件,需要给正文上面加一个标题。

实现方法可以通过设webview里scrollView的contentInset,在头部留好自定义view的空间,再把view添加进来,随着webview的滚动缩放细调这个view的位置。这里把这些行为封装了起来做成一个扩展的UIWebView,主要解决的问题是:

1.直接通过设headerView和footerView完成头尾view的插入。
2.webView滚动和缩放时自动调整headerView和footerView的位置,使之看起来自然。
3.提供接口实现头部高度改变时进行动画

有个问题未解决:

设置contentInset后,webview顶点的Y坐标不是0,而是小于0的一个数(负的headerView的高度) 。
在webview跳转页面时,会自动滚动到(0,0)位置,也就是跳到webview内容的顶部,也就是这时候headerView被隐藏了。

从调用堆栈来看这次跳转是私有的UIWebDocumentView调起,无法截获阻止。只能在触发scrollViewDidScroll时让它跳回去。但还没找到方法判断什么时候该跳什么时候不该跳。

[iOS]自动添加NavigationController自定义按钮动画

2012-2-21 评论(0) 分类:技术文章 Tags:

问题

UINavigationController顶部的返回按钮在切换视图时有左右滑动的动画(效果见iMail),但在自定义了这个按钮后(通过设self.navigationItem.leftBarButtonItem自定义),切换视图时按钮没有了动画。

最初解决方法

在每个viewController的viewWillAppear和viewDisappear方法上手动让按钮左右动。由于每个视图出现/消失的方向都有左/右两种,在这里难以判断,需要各种变量辅助,实现十分恶心,中间需要新加view时逻辑还要重新修改,被折腾。

最终解决方法

继承UINavigationController,重写pushViewController和popViewController方法,在这两个方法里面获取NavigationController里的view栈,因为push和pop总是操作最前面的View,所以可以从栈里知道哪两个view是要做动画的。调用这些view相应的方法使他们让自己的按钮动。这些方法可以写在UIViewController的扩展里,不用修改每一个viewController。

换言之,把下面的代码加入项目里,把项目里的UINavigationController换成下面的类,那些自定义的返回按钮就会自动做动画了。

代码

https://github.com/bang590/iOSPlayground/tree/master/NavigationButtonAnimate
(更多…)

[iOS]iOS开发初学者记录

2012-2-6 评论(4) 分类:技术文章 Tags:

做完了项目,想总结下,不知怎么写合适,只列出一些iOS开发的基础点,开发前因为不知道这些点,导致走了一些弯路,希望对初学者有帮助。

基础篇

为什么对一个变量release后还要设为nil

对一个变量release后,这个变量指向的内存释放了,但这个变量本身没变,仍指向原来的内存地址。若这个变量在释放后被访问,或者被重复release,就会导致应用崩溃。设为nil后这个变量指向0x00,可以保证程序以后访问不到原先的内存地址,对nil进行release也没任何问题。

使用类成员时,前面加不加self.有什么区别

不加self.调用的是成员本身,加self.后实际上调用了其成员的get set方法。
例:

//.h
@property (nonatomic, retain) NSString *name

//.m
name = @"bang";  //没有retain,随时会被释放
NSString *str = self.name  //等于NSString *str = [self name];
self.name = @"bang"; //等于[self setName:@"bang"]; 这时在set方法里retain了这个字符串

技巧篇

内存泄漏

可以通过xcode的编译工具Product-Analyze检查函数块范围内可能的泄漏点(外带会提示一些可能有的错误)。

用leaks工具监测出来的泄漏查找方法是跟踪其代码提示中出现的变量,经常这个变量是在提示的调用堆栈以外的地方泄漏的。若实在查不到,最终办法是重写这个变量的retain和release方法,debug,从调用堆栈看是谁retain了它而没有release。

要注意的是,用CFXXCreate(例如CFArrayCreate)生成的变量要用CFRelease释放。

数据存储

如无搜索需要,可以将一个数据对象直接序列化后存到sqlite,取出时直接反序列化为对象使用。序列化需要数据类实现NSCoding协议,实现encodeWithCoder和initWithCoder两个方法就行,若有多个数据对象,可以写个基类实现这两个方法,并在这里面利用反射枚举自身所有变量去encode和decode,一劳永逸,具体实现网上找找就有了。

组件篇

UINavigationController头尾显示隐藏

在用NavigationController去管理view的push和pop时,需要根据不同的view设置是否显示NavigationBar和ToolBar,一开始在错误的地方设置了,导致有时该显示NavigationBar和ToolBar时不显示的情况,后来发现在viewWillAppear上设置万无一失。别笑我土鳖,没好好去理解它整个流程,一直没发现。

- (void) viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    [self.navigationController setToolbarHidden:NO];
    [self.navigationController setNavigationBarHidden:NO];
}

UITableView游标式渲染

tableView的机制大概是:先定好总行数,某一行滚入视图范围时,回调一个函数去取view出来显示。这一行滚出视图再滚入时仍会继续回调这一函数取view。有这样的机制就是说无论你table里的数据有多少,都可以全部放入table中不用分页,因为不用一次性把所有数据都取出来,只在需要显示的时候根据游标去取对应的数据就行了。

可能这是APP组件很自然的方式不用说明,但在web上页面上的数据和元素都是要一次性载入内存的,做久了web,一开始没想到它这样的实现机制,导致我们走了不少弯路。

UIWebView渲染范围

UIWebView不是根据可视范围决定每次的渲染范围,而是根据自身控件的frame大小决定。

曾尝试webview嵌在tableview里,为了让webview跟tableview一起滚动,把webview的大小设为webview里的内容大小,让webview不出滚动条,从而能跟着tableview的滚动条一起滚。这样做的后果是每次webview都一次性渲染整个页面,内存占用多性能很差,而且在放大缩小这个webview时,渲染放大的整个页面更吃力,出现不能忍受的性能。解决办法是让webview定住高度为一整屏iphone的高度,限制了webview每次的渲染范围为可视范围,性能大好。带来的问题是无法随tableview滚动,但可以以其他方式优化体验。最近看到新版的ZAKER也是这样做的。

个人感觉篇

界面布局调整非常麻烦,让人怀念web了。界面描述方法XIB感觉晦涩难学,至今不会,没有CSS+HTML来得方便。

有编译器把关,少了像写js时多写or写错一个字符查半天的问题。

Object-C写起来各种变量函数和变量调用很长,没有js的短小精悍来得爽。

第一次编写涉及手动内存管理的程序,挺有意思,没想象中难,但有些内存管理导致的bug很难查。

虽然APP不像web那样随时更新,但也不像传统PC客户端升级那么麻烦,用户更新意愿更强,还是适合快速迭代的。

细节是可以决定成败,但得看你把什么定成细节。

最后,0bug的程序不存在,极致是把最主要的事做好。done is better than perfect。

为什么有困难不愿找警察

2012-2-5 评论(7) 分类:生活

去姐家吃饭,途径一摊位,写明移动联通电信充100送100,手机卡快没钱了,遂停下询问,他们说他们是通信公司的,现在有充100送100活动,移动联通电信手机卡都可以。我很笨,没戒心没细问,因为他的说辞跟校园里那些充值优惠活动一样啊。给两个手机号都充了,结果发现他是类似200卡的网络电话,钱是充进他们公司的不是手机卡里的,只能通过拨打他们的电话再输要拨的号码再挂机再等它来电才能接通电话,而且因为是网络电话,延迟很大。非常生气,理论了很久,不给退款,我说是诈骗,他说怎么会是诈骗我们有公司有营业执照打电话查询也查到账户里有200元,说我没问清楚这钱是不是充到移动的,那是我的事。周旋了半个钟无果,只能走了。

任何人都可以随便架一个服务器跟运营商内部的人秘密合作搞网络电话中转中心,成本很低,上街搞这些活动半骗着让人充值,充完确实有钱确实能打电话,对方就算觉得有被骗的感觉,也没办法,因为金额小,也不想再浪费时间惹麻烦,想着至少这100块还能用,事实是这些公司捞够钱后把后端的服务器一撤,就什么都没有了,电话肯定也是打不了了,什么责任都不用付。

如果他们一开始说这钱充完后是要怎样怎样打电话,不是充进移动卡的,然后我们买,那是完全没问题。问题是一开始就以技巧模糊地让我们觉得这跟普通移动充值没什么区别,只要没经验或不细心询问问到点子上就不会发现。事后他只要说你没问就行了,客户回想起来还只能怪自己,我觉得这就是诈骗。运营商跟这些公司是没有合作关系的,他们也痛恨这些做法,但太分散也难处理,若打电话问运营商客服,会被告知他们也知道这些行为违规,但也拿他们没办法,建议报警处理。

我是趋于不惹事不报警,但最后姐夫说吞不下这口气,报了警,经一小时处理后接受调解取消报警,对方还了钱了事。

说说为啥面对这些小额被骗的情况大多数人不愿报警。

1.畏警察

警察的形象怎样?不是全心全意为人民服务,而是能不接触就不接触,谁知道你遇到的警察是什么类型的,会不会反过来找你麻烦,公安局派出所这样的地方肯定是能不去就不去,最好一辈子都不跟他们打交道。

2.无所谓

以和为贵,报警给人感觉是很大件事的,一两百块的小问题不好意思麻烦警察局,想想也就算了。

3.怕麻烦,费时间

我报警时本来以为阿sir过来调解一下就完事了,没想到他就要求大家交身份证,收档口,一起到公安局走一趟。到了后还要等他整理资料半小时,最后我们是和解了取消报警了还简单些,否则就要录口供走流程什么的,极其麻烦和费时。

4.怕没用

你不知道这里的潜规则是什么,你会怀疑他们是否已经做好了公安那边的工作,说白了就是不信任警察,报警也没用。

5.怕报复

你找人麻烦,不给他好过,你又不知道对方的习性,怎么知道是不是黑社会,会不会仇恨心太强找你报复,你多少会有一些资料在他手上,进公安局的时候要登记身份证手机甚至家庭地址,只要他们想那是能报复到的,有这个可能性就足以让人畏缩。

最后说下,其实充话费的那三个人,除了其中一个比较叼外,另外两个还是比较和善的。阿sir们也挺不错,都挺友好的,会跟你聊聊天,说是学校刚毕业的吧,这些摆摊充话费的骗人的很多,一般人都不会信,但把他们赶走了下次还是再来,没用。

家乡见闻

2012-1-29 评论(2) 分类:生活

对比

过年串门,一半以上的人长辈碰到我们这种刚工作的人都会问工资多少。想知道你混得怎样,也会暗自跟自己的儿女或亲戚对比,像学生时期的分数那样,你多少分,我多少分,打个标签在头上,好学生,差学生。如果是公务员则可以免去问工资的环节,大家都知道公务员怎么回事,本身就是很高级的标签,跟打工不一样。不会问你喜不喜欢现在做的工作,合不合适,因为工作就是工作,为了賺钱的工作,肯定由不得自己喜不喜欢的。

还听说某某中专毕业现在淘宝做生意賺了很多,对比我们这些大学刚毕业每天打工拿几千的显得很有优越感,还被长辈们时常挂嘴上念叨对比,强调中专毕业。我觉得他们确实很厉害很牛逼,我佩服他们,但不应该老是比学历,不知是不是长辈们对教育报太大希望了,或者理解错误认为受教育多的人就理应比教育少的賺得多,其实没什么关系。賺钱需要的除专业知识以外的软实力都不是能直接从教育学到的。只要有对比的心,賺多少钱都是不够的,高一等低一等的。

那些早出社会的人现在比我们大学毕业的成熟得多,多了我们四到七年的社会经验,显得老成,而我们学生稚嫩之气尚未退去,在见一个小学同学时真的感觉相形见拙。不知道几年后会怎样。

礼节习俗

不知道其他地区怎样,潮汕地区传统文化保留得好,礼节习俗很多,有些比较形式,每个镇还会有所偏差,例如过年去亲戚朋友作客要带桔子,然后要把桔子带走,带走前主人家要拿多两个桔子放进去让作客的人带走,意为大吉来大吉去,主人家还送吉。还有很多一时举不出来,朋友走动无所谓,但如果走访长辈亲戚,礼节不到位会被说不礼貌,没教养。所有行为中礼节最多的是:婚丧,多到一般人都不知道,必须请专门的人说明各种步骤,有风水时辰吉言生冲克礼品等等规则,很多因为相冲相克等原因要认一个人作义父义母才能化解,有些这样认了也没什么感情,有时感觉尴尬。

麻将赌博

从小见我妈骂舅舅打麻将赌博,以及听一些打麻将赌博导致输到家破人亡的故事,对麻将和赌钱行为都视为恶行,玩物丧志,在我印象中像毒品一样一进去就出不来。但事实上不是这样,这里普通人家放一张麻将桌在家里招几个朋友过来玩通宵是非常常见的,一夜输赢几千几万也是正常的,不会视这为洪水猛兽,都支持至少不反对自己的丈夫妻子儿女玩这些。这还是这里维护关系维护圈子的几大方法之一:烟酒礼赌。跟网游一样只要不沉迷就没什么问题,而且还比网游好。

发展治安

陆丰是发展不起来的,一个地方要发展,就要有投资,如果想在陆丰投资办厂什么的,政府第一个上来,在你还没办成厂之前就把你吃光,曾经这里有几个挺好的厂,亿达洲空调和海马酒,现在都没了,听说这里的各种领导总是去厂里视察参观,一参观就是一把钱,都给参没了,賺毛钱。其他地方的政府,虽然也是吃钱,但懂得细水长流,先让老板賺到钱,再慢慢交费。这里还治安不好,无论是普通人家还是商家墙壁上随处可见喷着贷款以及一些夸张字眼后面附带电话的,非常猖狂,也不会有警察去抓。在外读大学的一般不会回陆丰发展,这点倒有点像出国留学得好的一般不会回国。

素质

会看到这里的人一些素质不太好的表现,代表部分,不代表全部。经常见到两辆摩托车甚至两辆汽车在路上相遇后停下来交谈,不管他们是否堵住了路。小镇路小,塞车的起因很多是门店前的摩托车摆不好占道或摩托车逆道抢道导致汽车没法前进卡在那里。某次坐大巴去其他镇时看到一妇女晕车直接吐在车上,袋子虽然没放在她前面,但也离她不远,也不是来不及用,第二次吐的时候还是吐地上。有时大马路中央堆了垃圾堆,家里附近的医院门诊墙边也常年是垃圾堆。

惬意生活

好像说的都是家乡不好的话,说说好的,对比城市,家乡生活显得惬意,工作时间不长,地点不远,中午摩托一开几分钟回家吃午饭睡觉,下午继续,晚上偶尔朋友来家里坐坐喝杯茶天下大势。邻居们各自熟悉,显得很有人情味。这里依山傍海,田园也不少,空气清新不会有污染,稍微中层点的人自己买个地盖个房子不成问题,很适宜生活。

2011

2011-12-31 评论(10) 分类:生活

结束了在百度的实习,回到广东,时隔一年,怀念北京的同事。

脱离学校,告别了可能是人生最自由的时光。穿梭于各种毕业照间,

定了工作,纠结后留在广州,在这过程中麻烦了一些人,深表歉意。

租了房子,华师附近,走路上班,还是熟悉的地方,让毕业的转变不那么剧烈。

参加了长达25天的腾讯入职培训,枯燥又很水的军训,听到好的跟不好的课,跟106大伙三国杀得爽。

正式进入工作,有点小迷茫,状态一般,少了点什么,作息时间跟大伙有时差,工作不规律,工作内容可能是我所能分到的最感兴趣的。

发生了一些我觉得恐怖的事,让我在充满焦虑和不安全感中度过了几天,幸好最终没事。感谢这些事,让我加倍珍惜现在的自由生活。

痛苦艰辛地学完了车拿到了驾照

去了云南旅游,确实是个美丽的地方,洱海坐船,茶马古道骑马,远望雪山,还记得丽江清酒吧“日光倾城”里歌手唱的《Scarborough Fair》,很美妙。我对旅游并不是很感冒,但偶尔这样出游一下去开阔的地方放松感觉挺好。

差不多成了果粉,买了梦寐以求的macbook air,终于拥有笔记本,用着感觉很好,让我觉得没有比这更合适的了。在我的G7出问题,垂涎iPhone的时候,公司年会上竟然抽到了iPhone4S,一阵狂喜。随后的霉运让我继续相信等价交换的机制。

只做了两个个人项目,即连伊书。还是自娱自乐型,只开发无运营。做即连过程中入门了linux,接触到底层的皮毛。工作从前端开发暂时转向object-c。技术进步速度缓慢。

几乎告别twitter,也不再弄推特中文圈了,这个带给我很多的东西的产品结束了,很希望能再做出这样的产品。

今年的博客是过去5年里写得最少的,可能是我懒了,工作后没时间了,和谐面变多了。如果我写的什么东西,技术之类,总结之类,不能放在博客上公开,我是没什么动力去写了。但至少,每个月一定至少会有一篇。

浪费了大量的时间,惰性增强,难以专注,没有时间管理,无所事事的时间变多,思考变少,这是今年最失败的地方。

还是在随着性子做事,不会勉强自己去做对自己有好处但让自己不舒服的事。我写着写着突然明白为什么我会出现那种恍惚忧郁的状态,因为出了学校,有些事情就要压在心里了,不能公开说了,以前没这样的压抑,我还不习惯。要开始各方面慎言,真的,很不习惯。

总的来说,大事顺利,小事一般。有时还会两秒内分不清今年是2010还是2011,就要到2012年了。希望2012一切顺利,身体健康,激情燃烧,奋勇向前,全面提速。能力不够,就无权享受到更大的自由,共勉。

伊书 – 苏菲的世界

2011-12-7 评论(8) 分类:作品 Tags:

伊书 – 苏菲的世界

介绍

距上次我在新浪微博发”I got an idea“已经过去快一个半月了,现在终于把这个idea完成了。

其实也不算idea,只是想认真地做一本针对iOS的电子书,webApp方式,最好精致点,取名伊书。

伊书是电子书,一本书一个APP,用webApp方式实现,打开浏览器,添加到屏幕,即可完成整本书的下载,随时离线浏览。伊书有以下特点和功能:

  1. 最基本的点击左右两侧滑动翻页
  2. 手指滑动拖动页面,在低版本的iPhone上性能会差一点,iPhone4以上较流畅
  3. 注释功能,点击正文上的注释按钮显示注释内容。
  4. 底部红条显示当前章节的进度,按住可以显示页码,拖动可以快速翻页。
  5. 夜间模式
  6. 排版:
    iOS5以上支持左右对齐的justify排版,iOS4以下不支持。
    书信开头的左顶格,落脚的右对齐,引用内容的。
    标点悬挂,将出现在行首的标点提前到上一行末。
  7. 当然它是离线的

历程

想起2001年有个网站叫E书时空(这个网站竟然还存在),提供电子书下载,一本一个exe文件,设计良好,很喜欢。想来我特别喜欢那种包装起来成一个完整个体的东西,像一本本电子书,一个个iPhone APP,还有一个个完整的FLASH游戏。像我以前做的Q版海底俄罗斯这个FLASH游戏,特别喜欢打造这样一个完整东西的感觉。

我是看到“唐茶”才想起这些的,非常喜欢唐茶这样的APP,很有苹果的风格,阅读体验上追求完美,确实是阅读新境界。手机阅读随时随地,我自己也在手机上读了不少书,自身需求较大,我想用自己的方式去实现一个。我没见过有人用web的方式做这样的电子书,算是实验尝试,也算是自娱自乐的项目。

第一本书我选择了《苏菲的世界》,觉得它很好,以非常轻松的方式让人了解整个科学哲学史。这部书原版出版于1991年,按理来说至今20年已经没有版权问题了,但翻译的版权还是存在的,所以这还是算盗版吧。整本书的内容是在网上找的,内容有非常多的错误,我见到的都一一修改了,光改内容已经花了我很多时间,相信这是网上能得到的版本最好错误最少的《苏菲的世界》。

工作后做业余项目真是不容易,时间太少,娱乐时间大部分都贡献出来了,有时是乐在其中,有时不得不去做琐碎的事情,不得不去做不擅长的设计,也是有点辛苦的。设计对我来说是个难题,设计的过程是憋出来的,一点点试出来,比较痛苦,很想自己的设计能力能提高,但很难,也很想跟好的设计师合做一个产品。

这个产品从80%到100%花了挺长时间,产品发布的页面都做了,还有在safari打开时针对高清屏的优化,总的来说,这次还是比较用心的。这样的产品,做出来感觉很快乐,但如果有人用,可以增加百倍的快乐,希望有人会喜欢吧。

iPhone webApp缺陷

苹果对webApp支持力度较大,在移动端对HTML5,对webApp支持得最好的就是iOS了,但它还是有很多缺陷。

  1. 无法阻止屏幕旋转
    只能做一个在旋转到横屏时提示“不支持横屏”的提示。
  2. 无法正常切换任务,一切换就重刷页面
    原生APP从后台切回来直接恢复状态,webApp跟iOS时代的APP一样,一切走,再切回来,就是重启应用。
  3. 不能调节亮度
    这个还可以接受,只是在阅读时比较需要这样的接口。
  4. 图标和开启页面无法使用manifest缓存
    manifest无法管到APP的图标和启动图片,每次打开应用都会去请求这两张图片。
  5. 头部状态栏无法去除
    少了一些宝贵的显示空间
  6. 性能
    iPhone4S上性能给力很多了。但是,原生APP可以流畅实现更炫的效果时,webApp不过是刚好能实现简单效果。

有点痛苦的学车经历

2011-11-17 评论(4) 分类:生活 Tags:

今年三月去华师里的华科大驾校报了名学车,因为考虑到工作后要再去学车考驾照就很麻烦了,没时间,趁着大四空闲赶紧在毕业前把这事给办了,结果办到现在工作N个月了才办成。挺后悔之前没有去报,大学期间应该尽快解决这种麻烦事。

教练

整个学车过程是非常不爽的,不爽在于教练,驾校也算是服务业吧,应该找不到第二个行业,服务比驾校更烂,即使是政府部门的服务也比他们好很多。

去学车的时候比较傻,我们几个人让驾校随机分配了个教练,袁教练,接着不爽的学车历程就开始了。说说这位教练差在哪:

  1. 态度极差。很重要的一点,辐射整个学车过程,N个小时的痛苦由此而来,仿佛每个学员都是笨蛋,脑子不好使,刚学车自然没有他这位十几年老车虫那么熟练,只要操作有一点不合他意(不一定是错误操作),就被他吼骂,仿佛天天更年期,百吼不厌。后来我发现他对我算仁慈了,最后一次学路面的时候,跟另一个40多岁的大叔一起学,他直骂那位大叔猪脑,垃圾。我都听不下去了,那位大叔年龄比他大多,竟然能这么骂,真够™混蛋的。
  2. 考试要买烟。每次考试,他都开口向我们要烟,直接载我们到小卖部门口去买,20多块一包的五叶神,不多,但也挺厚颜无耻的,刚开始考桩时还骗说是给那些考官的,这谎撒得很拙劣,后来索性不撒了,考完再载我们去买烟。似乎这间驾校的其他教官是没这嗜好的。
  3. 约练车,约考不跟人商量时间。练车和约考直接单方面给你定下时间,不来练车,就算你这节课学过了,不来考试,就算你挂了,交补考费下次考。导致我最后一次路面练得很辛苦,因为约考的时间很近,我又去旅游,回来后马不停蹄地连续4个早上练车,极其累。
  4. 教学才能全无。整个过程就是应试教育,非常机械地让我们对好点就完了,完全不会说什么原理,为什么要这样做。有时候一些完全没问题的做法,因为不符合他的机械教学方式,也会被吼停。
  5. 每次看他在上级和那些开着车过来练车的有钱学员面前点头哈腰的样子,我就忍俊不禁。

此教练姓袁,袁教练,记住了,去华科大驾校学车千万别选这个人。其他教练我不知道会怎样,当然是会有好教练的。在学车期间曾有几次让一个助理教练教,许教练,这个教练就很好,通情达理,悉心教导,每步都会说为什么要这样做,也很少吼人。可惜,只让他教了几次,剩下都在这姓袁的阴影下痛苦度过。

对以上两位教练的评价,我们一起学车的三个人都是很一致的。

我觉得驾校要控制教练们的态度和教学质量是很容易的,学员的考试通过率跟薪资挂钩,学员可以对教练进行评价,给个好评差评,也与薪资挂钩,这不很简单吗。驾校没这么做,考完车了我至今无渠道跟驾校反映这位教练的行径。可能因为就算教练素质再差,来报名学车的人也能源源不绝,就不用管这些了。

过程

学车过程不太顺畅,文科考试和桩考无压力,但接下来的九选三电子考挂了。九选三当时学到我们都恶心了,还没能过心情很糟糕。第一次考时感觉还挺轻松,很容易就完成斜坡起步和侧边停车,但当我觉得侧边停车已经完美完成的时候,车上的机器说话了,考试不合格,擦,莫名其妙,只能再来一次了,结果第二次我自己弄错了,侧边停车在入库倒车时倒多了,于是挂1档想向前走一点调好位置,结果那个SB电子监控以为我已经入了库再出来了,叫我马上进行第三项。于是我就挂了。挂了后那位袁教练用比我臭百倍的脸对我说,半年后再考吧!

第二次九选三时人工监考,容易多了,比较轻易地过了。接着长途很郁闷,跟一对情侣和一个社会人士一起去,都不认识,去到连南那个地方,比我家乡还破旧,住的旅店抽到一个很偏僻地非常差的。在非常的无聊中度过。最后的路面上面说了,很辛苦,还好最后过了,那位交警虽然一副黑社会样,但感觉还是挺好的,比袁教练要有素质。另,这位交警长得挺像韩红。

其他

考车不难,但每次考试前我都会挺紧张,很讨厌那种感觉,虽然在考车这事上这种感觉只是轻微的,希望这是我最后一次参与这种考试了。其实之前在找工作面试时,在上台演讲时,也有这样的感觉,紧张,这一小段时间的紧张没什么,主要是在此之前长时间的焦虑,比较困扰人。不敢放松下来,因为感觉松弛了不利于发挥,我应该是个心理很敏感的人,至今未能很好地解决这个问题。我惰性发作的时候,觉得是否有必要解决这个问题这是个问题,有人说人要跳出自己的舒适区去提高自己,但有时我发现不用辛苦地去迎合大众所认可的那些成功特质,只是在自己舒适地范围内发挥自己的特长,也可以过得很好。

QQ邮箱iPhone版 — 混搭式开发的尝试

2011-10-25 评论(9) 分类:技术文章 Tags:

QQ邮箱iPhone版开发了几个月,多次延迟发布,过程十分艰辛。这是第一次尝试混搭的开发方式,即整个应用主要由web组成,APP给web套上一个壳并提供一些原生的接口,以达到更好的体验。我们使用了开源的PhoneGap框架,但其实到后来已经可以抛弃它了,没用它多少接口,自己实现一下也只是时间的问题。

总体

整个APP主要是以下三点:

  1. APP由js驱动,与手机邮箱触屏版/ipad版使用同一套逻辑,同样的M层,架构一致。
  2. 由APP客户端提供绘制头尾以及动画切换的接口,由js调用。
  3. 使用HTML5的sqlite/localstorage缓存数据,applicationCache缓存静态文件和页面。

加上各种细节,就可以构建一个仿原生应用了。

问题

实际上说得简单,做起来难,碰到很多问题。

性能

DOM的性能差,渲染速度慢,最初在各个模块之间切换时速度不能忍受,经过各种优化后情况才好转。优化包括:去除所有高级CSS特性,例如阴影渐变等,减少list默认显示条数,缓存DOM,APP头尾控件缓存,APP动画拍照优化。即使经过很多优化,目前性能上还是跟原生APP有所差距。这种差距目前来看只能等待硬件升级。其实在未做任何优化前,在mac的模拟器上体验已经很好了,无性能问题,因为mac的硬件够好。

manifest

applicationCache的manifest是个令人头痛的东西,项目过程中几度出问题。它最大的不足在于不能清空缓存,一旦使用了它,将很难抛弃它,只能更新,不能抛弃。造成的问题是,manifest更新时,拉取新的资源文件,一旦主页面在后台输出的是个不正确的页面,被缓存起来了,就万劫不复,再也无法进入应用了,因为没有机会再次取拉正确的页面了。所以要使用它,需要强力保证主页面绝不会输出错误,最好是个静态页面。

此外用manifest还要非常细心。项目过程中有两次出现突然无法离线的情况。一次是manifest针对高清屏输出的文件有个地方没换行,导致缓存无效。很难看出它没换行,因为manifest文件是套模板的,模板上是有换行的,转完输出就没有了。只针对高清屏错误就导致模拟器和iphone3都没问题,只有iphone4有问题。折腾这个诡异的问题半天。另一次是写在APP里的启动网址参数里多了个’s’,导致打开的页面跟缓存的页面不一致,很难发现,也查了挺久。

JS-APP不同步

APP提供了绘制头部底部的接口,何时绘制以及绘制什么由JS控制。模块的切换会有动画效果,在js调用模块切换时,先拍照,再画头画底,再回调开始动画的事件,JS渲染自身的dom,动画切过去,整个流程挺简单挺清晰,但实际会有各种问题出现。

在初期经常出现APP头尾和模块内容不一致的问题,由各种原因导致,可能在切换模块整个流程没结束时马上又切换模块了,或者再调一次画头尾,会打乱流程。这通过APP那边把命令加入一个队列顺序执行,并且在动画过程不响应事件来解决。

登录问题

由于历史问题,登录没有使用ajax,整个应用不可避免地需要页面跳转,这会导致非常多的问题:
1.在某些网速非常慢的情况下,整个应用白屏无法避免,因为在跳转了页面并且页面还未载入时,必然会先出现一个空白页面。
2.登录的loading菊花卡住不转,因为跳转了页面本页面的无论是gif还是canvas都停止运行了。
3.一旦出现运营商劫持/wifi验证页面,整个应用就会调转到这个页面去,完蛋了。这个后来通过把表单提交到iframe解决。
所以,最好不要出现跳转页面的情况,必须整个应用在一个页面里。

沟通成本

本来一个iPhone APP的开发链就是,UI-客户端-后台,加入js后,多了js与客户端沟通的成本。而在这种开发模式不成熟的时候,这个沟通成本挺大。另外在APP出问题的时候,有时挺难判断是js的问题还是客户端的问题。

由于APP介入了表现层,进入JS的逻辑,所以必须对APP和JS两端都熟悉了解,才能掌握整个流程。之前不清楚为什么phoneGap不推出这个固定画头画底的接口,这是所有APP必备而在web上实现性能又很差的东西。现在知道这会使APP变复杂,phoneGap只提供功能接口,作为后台角色,其他全交给JS,不需要与APP进行过多的沟通。

webView/网络

出现了一些问题我们还没弄清除是不是webView的问题,例如,记住cookie的问题,登陆过后是设了cookie的,但如果这时马上退出,下次进来就不会有cookie,如果是隔个二三十秒过后再退出,cookie就能记住。非常奇怪的行为,对此我们只能打个补丁,把某些cookie存到localstorage,下次进来如果没有cookie就从localstorage里取,这个方案还依赖了mainifest。

另一个是APP环境改变时ajax的行为问题,在请求或者上传时,APP切换到后台,APP切换网络,APP切换到后台长时间不用再打开,APP终止webView的请求,都会由可能导致ajax卡死,无onsuccess或onerror的callback,有时还会导致JS被阻塞,接下来无法正常响应请求。这是我们框架的缘故,还是webView的缘故,还待查。

好处

与纯原生APP比,它是有带来一些好处的。

  1. 云端升级:应用的某些升级无需通过AppStore,无需用户下载安装,可以快速迭代。
  2. 代码复用:触屏版/ipad版的多数代码可以复用或者共用,降低开发成本,提高开发速度。
  3. 跨平台:我们暂时没用到这个好处。若要跨平台,数据层没问题,VC层还是有很多的不同。

总结

混搭的开发方式,APP最好不要参与到表现层的东西,只提供必须的功能接口,否则js与APP一起管理整个表现,会导致复杂度增加,开发困难。但目前没办法,可能走得有点快,就目前来说,纯web的表现还与APP的差距甚大,必须借助APP的力量,像最基本的头尾固定,只能由APP来展现。

目前iOS5的浏览器支持了position:fixed属性,可以在屏幕上固定元素,支持-webkit-overflow-scrolling: touch,可以原生支持对区域滚动,就具备了使用纯web实现目前的体验的基础。等接口提供再加上硬件不断加强,性能上的差距也会缩小,等市面最低版本是iOS5了,硬件都升级了,web主导的这类应用估计会多些。