Uncategorized
荐书:Cocoa Programming Developer’s Handbook
by Robin Lu on Dec.31, 2009, under Uncategorized

最近有机会读到Addison Wesley即将出版的新书Cocoa Programming Developer’s Handbook,感觉非常好。
目前市面上Cocoa编程的书,比较有名的象O’Reilly的Learning Cocoa with Objective-C,Addison Wesley的Cocoa Programming for Mac OS X,可以将一个完全不懂Cocoa编程的人带入门。而入门之后,似乎就只有苹果官方文档可看了。对于一些有一定编程经验,又希望学习一个新编程框架的人来说,那些从ABC讲起的编程入门书往往会让他们觉得花了时间却学不到什么东西,他们更需要一本直接告诉他们这个框架能做什么和怎样去充分利用这个框架。从入门到成为一个有经验的Cocoa programmer,有一个很大的落差,其中的经验和相关知识散落在官方文档、官方实例、开源项目和各种各样诸如Cocoadev的知识库和Cocoa With Love这样的blog之中。缺乏一本书,能够把入门者从浩如烟海的官方文档和口口相传的经验中解救出来,给他们一个更全面和深入了解Cocoa的机会。
Cocoa Programming Developer’s Handbook就刚好填补了这个空白,达到了这个目的。这本书首先是内容很全,八大部分二十五个章节九百多页,是目前市面上涵盖Cocoa内容最广的一本书。另外,它的内容非常新,包含了Mac OS X 10.6的许多新特性,实际上它的预计出版日期是明年一月。更重要的是,作者David Chisnall是Cocoa的GNU实现GNUStep的贡献者,有丰富的Cocoa和Objective-C的开发经验,不仅把很多技术的来龙去脉讲的很清楚,又有很多Cocoa编程的最佳实践,这些都是从API文档中很难获得的知识。读这本书就象和一个Cocoa高手交流的过程,读起来可以说是饶有兴味。
但需要说明的是,这本书可能并不适合用来入门,不会去手把手教你如何从无到有实现一个Cocoa应用。同样,它也无法代替官方API文档,不会去介绍每个method的使用细节。它讨论的更多的是”big picture”和”best practice”,是paradigm和pattern,让一个有一定经验的程序员可以更快的进入Cocoa的语境。另外,它不是一本讲iPhone编程的书,但它对iPhone程序员一定会有很大的帮助。
可以说,这就是我一直想要的那本Cocoa编程书,翻看了电子版后,已经在amazon预订了印刷版。如果有国内出版社可以将此书引进,功德无量。
北京Ruby/Rails开发者聚会
by Robin Lu on Nov.11, 2009, under Uncategorized
好了,北京也要有Ruby/Rails开发者的活动了。
本周六,Joyent赞助,InfoQ牵头,我们财帮子三个人都会去。具体时间地点看链接。
希望这次能开一个好头,把北京的Ruby/Rails社区活动搞下去。
KungFu Rails小记
by Robin Lu on Oct.26, 2009, under Uncategorized
上周末赶去上海参加了KungFu Rails中国Rails开发者大会。本来因为女儿发烧,差点去不成,最后夫人鼎力支持,终于成行。
这次Rails开发者大会整容相当强大,演讲也很精彩。Rails 3的主导开发者Yehuda Katz来做了关于Rails 3的介绍,比起五月份Rails Conf看到的Rails 3介绍,又多了一些新内容。github的Scott和PJ双双到场。Scott的视频我是看过一堆了,第一次听到现场。PJ在创立github前,我就很fan他的err blog。刚好InfoQ还给我们了一个机会,采访了Scott和PJ,问了不少git和github的问题,他们两人也很健谈,相信视频很快会在InfoQ上看到。台湾来的張文鈿讲的Rails Best Practice: Write Better Code,实用性很强,是这次大会的一个亮点,据说还得到Yehuda同学的青睐。易空海黄志敏写的Rails插件Bulletin最近获得Rails社区广泛的关注,这次他来分享了如何制作gem和plugin的经验。我们团队的Louie Zhao讲了一下使用Integrity做持续集成和使用metric_fu做静态代码检查的经验,演讲的slides和更具体的内容都分享在这里。另外《JRuby实战》的译者丁雪丰,易空海的郜磊,也都有精彩的演讲。唯一遗憾的是本来很期待的高桥征义的演讲,不知道什么原因不太流畅,高桥流简报法的威力大大缩水。
这次KungFu Rails收门票,虽然不贵,但人数明显少于上次RubyConfChina。不过有一个好处,就是来的人都是铁杆Rails开发者,结识这样一批人让人很开心,更觉得不虚此行。
我们三个人以IN-SRC Studio的名义赞助了这次活动。这是今年第二次赞助这样的活动。碰到很多人来问,又不搞宣传又不招人,为什么赞助。其实我们的想法很简单,我们是ruby和rails的受益者,虽然没什么钱,但既然有人不辞辛苦来组织这样的活动,能帮一点是一点。在中国有这样好的rails活动,却没有一个中国人赞助,说不过去。对于社区乃至大环境,不知道这样的蝴蝶翅膀能改变什么,但我们除了空谈和抱怨,还可以做点别的。
这次另外一些收获,就是向Shanghai On Rails 小组请教了一下他们平时开展活动的经验。其实北京的Ruby和Rails开发者也不少,却少有线下交流的机会。也许我们也可以开始组织一些活动,希望可以尽快开始。
最后,这次活动的一些照片,分享在这里。
浅谈Blocks
by Robin Lu on Sep.06, 2009, under Uncategorized
在上次的Snow Leopard tech review摘要中提到,Snow Leopard(实际上是Xcode 3.2附带的编译器)开始支持Blocks。这是一个非常有意思的功能,以前通常只有一些动态语言支持,而现在,C/C++/Objective-C也可以用上这个功能了。
Block, 简单的说,就是一个函数对象,和其它类型的对象一样,你可以创建它,可以赋给一个变量,也可以作为函数的参数来传递。计算机科学中,更常用的名字是”closure”或者”lambda”。先通过一个例子看看什么是Block:
1 2 3 4 5 6 7 | void (^hello)(char*); hello = ^(char* str) { NSLog(@"hello %s", str); }; hello("robin"); |
这段代码申明了一个block变量hello,然后用一个block对象为它赋值,最后调用了这个函数。这是打印出的结果:
2009-09-06 16:36:12.693 blocks[6379:903] hello robin
再看一个例子。玩ruby的都知道each方法,可以很方便的遍历一些数据组合。比如:
[1,2,3].each {|x| puts x }
就可以打印出
1 2 3
现在,我们也可以为NSArray加上这样的方法。我为NSArray写了一个Category,加入下面函数的实现:
- (void)each:(void (^)(id))block { for (id obj in self) { block(obj); } }
很简单,我们就有了一个属于NSArray的each。看一个调用的例子:
NSArray * array = [NSArray arrayWithObjects:@"tom", @"jerry", @"robin", nil]; [array each:^(id obj) {NSLog(@"hello %@", obj);}];
首先,生成了一个数组对象,里面有三个名字,然后分别向这三个名字说hello。
再来为NSArray实现一个select方法,这个方法为每一个数组中的对象调用block,这个block做出选择,选中的返回true,最后select函数返回一个数组,其中包含所有选中的对象:
- (NSArray *)select:(BOOL (^)(id))block { NSMutableArray *rslt = [NSMutableArray array]; for (id obj in self) { if (block(obj)) { [rslt addObject:obj]; } } return rslt; }
再看一个调用的例子:
NSArray * array = [NSArray arrayWithObjects:@"tom", @"jerry", @"robin", nil]; [[array select:^(id obj) { return [obj isEqualToString:@"robin"]; }] each:^(id obj) { NSLog(@"hello %@ only", obj); }];
依然生成包含三个名字的数组,但是先调用select,只选出’robin’,然后只向选出的名字说’hello’。
看到现在,应该已经对block有一个初步的认识了。也许会产生一个疑问,block和函数指针有什么区别?
第一个区别,函数指针是对一个函数地址的引用,这个函数在编译的时候就已经确定了。而block是一个函数对象,是在程序运行过程中产生的。在一个作用域中生成的block对象分配在栈(stack)上,和其他所有分配在栈上的对象一样,离开这个作用域,就不存在了。这是一个Xcode文档中的错误案例:
void dontDoThis() { void (^blockArray[3])(void); // an array of 3 Block references for (int i = 0; i < 3; ++i) { blockArray[i] = ^{ printf("hello, %d\n", i); }; // WRONG: Block literal scope is "for loop" } }
另外,block对象在一个作用域中,在这个block之中可以访问同在这个作用域中的本地变量。我们来看一个例子:
void say(NSString *something) { NSArray * array = [NSArray arrayWithObjects:@"tom", @"jerry", @"robin", nil]; [array each:^(id obj) { NSLog(@"%@, %@", something, obj); }]; }
这个函数是向数组中的名字说点什么,具体说什么,在block中并不确定. 因为each本身接口的限制,也没法通过函数的参数传入。如果用函数指针来实现,就不可避免的要引入全局或者静态变量,而使用block,则完全没有这个问题。避免使用全局以及静态变量最直接的现实意义就是,更容易写出线程安全的程序。
通常情况下,block对同作用域中本地变量是以只读形式访问的,如果希望以读写方式来访问,需要在申明这个变量时加上__block。
本文的例子放在github上了,其中对NSArray还实现了map和reduce。
如果希望对Blocks做更多的了解,可以参看Xcode中的”Blocks Programming Topics”。
Snow Leopard Ars Technica Review 摘要
by Robin Lu on Sep.03, 2009, under Uncategorized
每次Mac OS X升级, Ars Technica都会有一个长篇的评论, 这次也不例外, 有23页之长. 原文在此. 边看边将我比较感兴趣的部分摘要了一下.
Snow Leopard是一次主要针对开发者的升级, 预告时就打出了0 feature的噱头, 最终用户能体验到的变化也许不多.
安装
安装大小有比较显著的变化, 比Leopard小很多. 排除Finder采用十进制方式展示空间大小的原因, 真正节约了空间的地方包括:
- 可运行码中不再有PPC部分.
- 很多文件采用了压缩模式, 利用extended attributes, 以ResourceFork的形式保存. 从之前版本的Mac OS X会是一个0大小的文件, 但在文件拷贝的层面做到了向前兼容.
- 对于更小的文件, 会直接保存在extended attributes中, 而不再单独分配一个块(通常是4K).
- 压缩存放文件, 一方面是节约了硬盘, 另一方面以CPU换I/O. 将内容存放在extended attributes中, 可以减少硬盘磁头的移动. 一切都是为了更快的读写速度.
安装过程中过检查不兼容的程序.另外, 安装增加了掉电保护功能.
64位
64位内核
K64(64位内核)并没有在所有的系统上被激活, 目前缺省激活的只有08以后的XServers. 要想在其他K64-capable的机器上启动64位内核, 需要在启动时同时按下6和4两个键. 或者用nvram直接修改启动配置.
64位内核最直接的好处是可以使用更大的内存. 更多的寄存器, 新的寻址方式和浮点运算能力对性能提升有帮助, 但只有少数程序(通常是server-based的程序)用到了这些特性, 对更多的日常应用而言, K64没有你想象中那么有用.
对于安装了96GB内存,并且不存在32位驱动程序困扰的人, K64是首选.
雪豹的32位内核同样支持64位应用, 在不耗尽内核地址空间的前提下, 不妨碍使用超过4G内存.
雪豹中64位应用明显增多,大量新API不再支持32位, Objective-2.1的很多新功能也只能用于64位应用程序.
苹果在用自己的行动拉拢大家进入64位阵营.
QuickTime X
X means ‘Ten’. 目标是淘汰已经18年之久的老QuickTime API. 但只是一个开始.
QuickTime X是纯64位. 部分功能仍依赖于32位的QuickTime 7. 通过启动一个独立的32位QTKitServer进程来完成64位应用对32位应用的使用.
QuickTime X API提供比之前更合理的资源使用方式, 只做你需要它做的事情. 对部分显卡支持GPU加速播放H.264.
文件系统API
用NSURL和CFURL统一文件引用.
引入Bookmark.
Do more with more
我们的硬件越来越好, 但运行速度并没有明显的改观, 原因之一是软件开发并没有充分利用这些提升. 雪豹的目标之一就是让开发者可以享受到硬件提升带来的好处, 在更好的条件下做到更多.
LLVM和Clang
隆重推出LLVM和Clang. 可以采用GCC, LLVM-GCC, Clang等多种编译方式. 在对特定硬件的优化上, LLVM比传统编译方式更具优势.
LLVM和Clang的组合, 编译速度更快, 编译出的可执行代码运行速度更快. 更友好的错误提示. 支持代码静态分析.
Blocks
Blocks的支持, 使C++, C, Objective-C也可以拥有过去只属于动态语言的closures和anonymous functions的特性.
不同于函数指针, Blocks提供更灵活的参数传递和变量上下文方式. 和真正的动态语言相比, 仍然有所限制, 需要遵守一系列规则.
Grand Central Dispatch
简称GCD, 是雪豹提供的新的基于C语言的并发运行机制.
通常,应用程序很难根据CPU的数量和使用情况来控制线程的数量. 多了, 增加调度成本. 少了, CPU闲置.
GCD提供统一的线程调度机制. 应用程序将任务放入GCD的任务队列, GCD根据硬件的具体情况产生数量合理的线程, 将任务逐个发送到这些线程中并发运行. 无论是双核还是八核, 同样的程序通过GCD可以充分利用硬件资源, 硬件升级对应用程序透明. GCD线程池中的线程被队列中的任务不断重用, GCD队列比线程更轻, overhead更小(512KB vs 256B).
异步
尽管有GCD, 我们仍然面对数据共享, 锁等等同步问题的困扰. Apple通过GCD, 鼓励开发者用一种异步的思想来解决同步问题,将程序分成主线程和完成繁重工作的工作线程.
GCD队列中的任务,实际是通过Blocks来实现的, 可以将运行单位限制在很小的范围内,更容易控制运行上下文, 同时也很容易将本来有同步问题的代码送回主线程来完成.
GCD让异步运行和充分利用CPU变得前所未有的简单.
OpenCL
OpenCL是有关于如何充分利用GPU. 苹果希望通过OpenCL, 将一些适合与在GPU上做的运算,比如一些矢量运算,交给GPU. 基于现实的考虑, 苹果在设计OpenCL时, 并没有限定OpenCL程序只运行在GPU上, CPU也可以作为可选设备之一, 扩大了OpenCL的使用场景.
OpenCL对上层统一接口, 却可以根据底层不同硬件做实时优化, 完全是依赖于LLVM强大的JIT编译能力. OpenCL还使用了GCD来处理任务并行.
到此, 雪豹已经将硬件能力挖掘的淋漓尽致.
其它
Input Managers, SIMBL plug-ins不再被支持.