电脑技术学习

从Windows的角度看Mac OS X上的软件开发

dn001

表二:开发语言与API的对照

图形作业环境的差异:绘图系统

大家对OS X最主要的印象,想必还是它的图形作业环境。GUI的确是OS X与Windows差异最多的地方。

在Windows环境里,传统上Win32 API同时包括了绘图(所谓的GDI/GDI+)和GUI组件(窗口、对话盒、按钮等等)的操作。到了.Net 3.0有所谓的WPF (Windows Presentation Foundation)。严格说来所有Windows上的概念和组件,都可以在OS X上找到相对应的作法。但是在架构上OS X确实和Windows有相当大的差异。

OS X的绘图系统核心是Quartz。Quartz的绘图基础概念是路径(path),而不是像素(pixel)。惊人的事实是:Quartz是一套PDF绘图系统。所有Quartz能绘制的对象都能轻易转换为PDF文件。至于在图像处理上,Quartz提供了一套完整的合成模型(compositing model)。简单地说,Quartz赋予了Mac OS X极为优异的绘图能力。从一些细节就可以看出Quartz在视觉上的细致度:例如,OS X在显示字型时的去锯齿(anti-aliasing)处理就要比Windows来得细腻,在点阵影像的缩放上效果也往往比Windows好。OS X的应用程序可以轻易做出各种透明度的图层、以及为图形对象加上阴影、或者绘制不规则形状(但这并不代表你应该只是为了为了吹嘘而滥用这些功能,我们马上会提到用户体验这件事)。倒是有个细节应该马上一提,那就是Quartz的默认分辨率是72 DPI,所使用的单位是点(point),这跟PDF绘图系统是一致的,和Windows预设为96 DPI、以像素为单位的点阵式绘图系统很不一样。这在一开始可能很困扰人。因为在OS X上,不改变屏幕设定的情况下,12 pt的字,就真的会被会绘制成12 px(而在Windows上,12 pt却是16 px)。同时,Quartz默认的坐标系统跟数学上的习惯相同,也就是(0, 0)坐标起点是位于左下方,而不是一般计算机绘图使用的左上方(当然,Quartz有各种坐标变换功能,因此当然还是可以把(0, 0)设定为左上方的)。

看似复杂,然而,当你开始想输出PDF(打印作业大幅简化)或进行精细的绘图工作时,慢慢就会发现Quartz这样设计的直观了。

另外,Quartz的基础API是以C写成的,所有对象操作方式都跟CoreFoundation一样(从Quartz建立的对象都是用reference counting的方式在管理内存,同时也都可以用CFRelease来释放)。不过,Cocoa也提供了绝大多数的API对应。使用Objective-C来操作绘图对象会更轻松些。

在Quartz之上,或者与Quartz并行的,还有Apple的各种图形和媒体相关的子系统。诸如可以快速制作动画的Quartz Composer、新一代文字输出编排系统CoreText、应用层的2D动画系统CoreAnimation,以及Apple的招牌多媒体架构QuickTime,还有业界标准的OpenGL,这些构成了Mac OS X在视觉及媒体经验上的核心。#p#分页标题#e#

图形作业环境的差异:GUI,以及,用户体验

Windows上,尤其是Win32 API里面,绝大多数关于GUI的概念和技能,都可以直接转换到OS X上。OS X的GUI同样是采用事件驱动模型(event-driven model)来设计的,每个GUI应用程序同样都有所谓的run loop(或称event loop/message loop)。两者甚至在某些系统限制上也雷同:例如,.Net跟Cocoa都不鼓励或甚至禁止程序在主线程以外的地方创建或操作GUI对象。

尽管如此,GUI是造就Mac OS X在外观上与其他平台不同的最大要素。与之相伴的是OS X对于用户体验近乎执着的追求。

OS X在GUI上并没有一个特别的子系统。通常我们用接触到的API来区分。好比说如果用的是Carbon我们会称为HIToolkit,如果用的是Cocoa则会说是AppKit(Cocoa主要是由非GUI的Foundation──不要和CoreFoudation搞混了──以及提供GUI组件的AppKit所组成的)。Apple的开发工具中并没有类似Visual Basic一类把接口画完、在组件上点两下鼠标,把程序填进去就完成应用程序的工具或流程。最接近的是Interface Builder (IB)这套工具。IB做出来的.nib文件其实就是封存好的GUI对象,生成之后再回Xcode将必要的连结关系拉完,程序代码填上(通常量不会很多)就完成程序了。IB会是Xcode以外,OS X开发者最常用的工具。

OS X提供的GUI组件特色为细腻、一致、直观。这并不代表OS X的GUI无法做复杂的设定和客制化。但是相较之下,OS X的应用程序更倾向于善用或组合现有的视觉元素,而较少自创新的custom control。这一点和Windows上,尤其是小型工具程序,喜欢一种程序就创造一种视觉风格,或是大量提供使用者可更换的skin,有着相当大的文化差异。虽然Apple自家的软件跟微软相似,喜欢提前使用下一个版本才出现的视觉风格或元素,有时让开发者觉得难以捉摸,但大体上遵守Apple自家的HIG (Human Interface Guideline)还是常态。

我们提到了文化差异;OS X在视觉上的细腻,以及对用户体验的追求,造就了一种高要求的文化。这可以说是一种正向循环。我们或许很少听说哪个Windows开发者会为了icon向左偏了1 pixel而大改特改,或是要求自己的软件要在视觉及操作上符合哪个规范的一致性。但OS X的开发者真的会谈论并严肃看待这件事情(著名的icon设计商IconFactory以及独立软件商Panic是著名的两个代表),同样的也有相当多OS X使用者以同样严苛的标准看待他们使用的软件,甚至可能写信告诉你,指出你的软件在用户体验或视觉设计上的缺陷(笔者就曾经收到使用者来信,指出笔者的一个软件在pull-down menu中使用的icon「语意」不合乎用户对该种GUI组件的期待)。又好比说,从OS X 10.5 Leopard开始,icon最大可以大到512x512,Apple也强烈建议开发者要准备这么大的尺寸(除了原有的16x16、32x32、128x128之外)。这当然无形中提高了开发的挑战。Windows在XP以前仅支持16x16、32x32、48x48,直到Vista才开始加大到64x64和256x256。

另一个与GUI不直接相关,但却影响用户体验的,是OS X的本地化(localization)系统。这一点也是和Windows不同的地方。OS X因为有bundle的设计,因此能让一个应用程序同时包装各种不同语系的资源文件,同时开发多语系程序在OS X上也相对容易(通常是以提供各种不同版本的.nib bundle放进应用程序bundle中Content/Resources/底下以语系区域来区分的子目录中就完成了。Windows程序设计一向以"resource file"概念来管理icon及本地化等「外部」资源,名称相似,开发方式却不那么一贯而直观;另外,OS X的语系是可以按照顺序fallback的,例如要是繁体中文语系档找不到,而用户在语言设定中将简体中文设定在繁体中文的后头,那么OS X便会尝试套用简体中文语系档),结果是OS X使用者对本地化同样有着高标准与高期待。另一方面,笔者也建议大家,除非软件确定只有中文用户使用,不然一开始先以英文界面开发,再加上中文的本地化资源,以长期来说是值得(甚至是必要)的投资。

一些较难归类但同样重要的差别

Mac OS X跟Windows在软件开发作法上的差异还有很多,上述只就最大的方向差异阐释。有些较细微但值得一提的差别,我们也在这里简单说明。

首先,OS X跟Windows一样,内部字符串编码以Unicode为准。但在操作系统不同的层级,使用方式并不相同。Windows的Unicode layer很一致地使用了UTF-16作为编码,并偏好使用BOM辅助判别。OS X的文件系统使用UTF-8,而CoreFoundation及Cocoa则用UTF-16。如果使用Cocoa自己的serialization机制,Cocoa会正确储存和还原UTF-16的位顺序。不过,笔者自己建议,尽可能使用UTF-8作为各种交换时的编码(相对于Windows对于UTF-8的支持不够干脆简明,Cocoa自己就提供了像stringWithUTF8String以及UTF8String两种NSString的method,方便在native string与UTF-8间的游走)。

其次,相对于Windows使用registry来管理应用程序设定,Mac OS X使用的是一种叫做property list(文件扩展名为.plist,简称plist)的XML文件。Plist可以直接变成CoreFoundation及Cocoa的各种容器对象,也可以将后者轻易地serialize成plist。因此OS X上的应用程序大量使用plist作为配置文件的格式,甚至作为数据单元格式。将设定用个别文件储存也减少了Windows集中管理registry所带来的各种弊病。

Mac OS X并不使用COM (Component Object Model)来作为面向对象的进程间通信(IPC; interprocess communication)的机制。因为用Cocoa写成的程序,可以透过Objective-C Distributed Object (DO)这个强大机制来达成IPC的任务。除此之外,因为bundle架构,OS X软件要设计外挂模块架构也相当容易。OS X有相当多支持外挂的应用程序,应归功于这种开发上的便利度。

OS X应用程序能够利用所有OS X在UNIX环境上所提供的功能。同时OS X一安装好就已经帮你准备好了大量的open source链接库,例如可用来制作密码密钥认证的OpenSSL、负责解压缩的libz、内嵌式数据库引擎SQLite等等。这些都是加速开发的好帮手。#p#分页标题#e#

最后要提的是,正因为OS X的文化与Windows有许多不同处,笔者建议跨足OS X的开发者应该要尽可能贴近甚至配合OS X的习惯。举例来说,大多数OS X应用程序都不需要安装程序,只需要直接将软件拷贝到想要存放的目录(通常是/Applications)即可。而解安装也就直接删除该.app bundle就解决了。在Windows上就没那么容易了(特别是有相当多组件依存关系的软件)。这些都是开发上需要注意的地方,但是开发者多付出一份心力,使用者就会多一份便利,终究会得到用户肯定的。

项目; Windows; Mac OS X
系统内部编码 Unicode (UTF-16) Unicode (文件系统使用 UTF-8, 系统API一般使用 CFString/NSString, 内部使用UTF-16)
语系处理 区分Codepage 不区分Codepage
应用程序的设定管理方式 Windows registry Property list files
IPC的几种方式 COM/Windows RPC Objective-C Distributed Object/Apple Event/BSD Socket
脚本语言的支持 VBScript/JScript/CScript/DOS Batch script AppleScript/Perl/Ruby/Python/shell script

表三:一些重要的系统特性(摘录)

项目 Windows (.NET) Mac OS X (Cocoa)
字符串处理 System.String NSString
数据结构与容器 System.Collections NSArray/NSDictionary/etc.
HTTP网络存取 System.Net System.Net,NSURLConnection
XML解译 System.XML NSXMLDocument etc.

表四:几个代表性的.NET namespace/class在Cocoa中的对应class

跨平台的建议

最后简短分享一些跨平台软件开发所可能遇到的问题。

要同时在Windows和Mac上开发,有两种可能的思维方式。一种是追求真正的"write once, run everywhere"。此时开发的选择,可能是采用Java平台,Adobe的AIR,抑或使用C++搭配像QT这样的跨平台链接库。这三种主流方案各有千秋,但在视觉和用户体验上往往皆无法与原生(native)的Mac应用程序相比。

因此,另一个方向则是体认到,要保有Windows及Mac各自平台的特长,就必须割舍GUI跨平台的可能性。也就是说,GUI是最无法移植到其他平台的部分。我们能做的是将共通的逻辑部分独立出来,然后开发两套前端接口(frontend)。若以在Windows及Mac上皆能使用为前提,共通逻辑开发语言的选择就很少了,不是C就是C++。所幸Windows和Mac上具有平台特色的语言,要和C++结合,也不是那么困难的事(在.Net上是透过C++/CLI,在Mac上是透过Objective-C++这两种扩展的语言)。

不过,在开发共享部分的时候,最容易碰到的问题,恐怕还是要如何省下力气去做例如解译XML文件、存取网络这一类不是GUI的工作。这类工作的麻烦在于,Windows和Mac都各自提供了相当便利、但也绝对和平台相依的链接库(例如.Net的System.Xml,Cocoa的NSXMLDocument)。在这种情况下,我们也大体有两种选择:不是全部采用跨平台的链接库(例如使用expat来解译XML),就是善用面向对象的抽象化以及Abstract Factory这样的设计模式(design pattern),让程序逻辑呼叫抽象的接口,然后在于各自平台的版本中藉由呼叫平台相依的API来实现这些对象。

结论

本文简要地讨论了Windows及Mac OS X在操作系统架构、开发环境、API、图形环境等环节上的相近处与不同的地方,也简单提出了跨平台应用程序开发的两种策略。事实上在两种平台上开发所需要了解的概念跟技能没有太大的不同,两种平台在性能上的差异也不大,但是在实现细节、视觉表现与用户体验上,OS X有自身独特的风格与文化。OS X软件开发社群常常说要"be a good Mac citizen"意思也就在此。了解这些差异和独特性是撰写合宜的OS X软件的第一步。

标签: