-
-
[转帖][分享]从Windows的角度看Mac OS X上的软件开发兼谈跨平台开发的一些可行方向
-
发表于: 2011-3-21 10:49 6354
-
如果原来从事Windows软件开发,想跨足或转换至Mac OS X环境,需要知道那些东西?有什么知识技能可以快速运用在Mac OS X环境上的?这两个问题应该是Windows开发者进入Mac OS X环境最关心的问题。本文假设读者以往采用微软的开发工具,并以C/C++/C#的任一种组合作为开发语言。
大体说来,Windows和Mac OS X都是为桌面应用环境、图形用户接口(GUI)而设计的操作系统。虽然不同平台细节各有特色,但两者相近的抽象概念,其实远远多于相左之处。本文试图指出 方向上明显的异同所在,而非详细列举各种细项差别。最后,我也将简短分享自己在开发跨平台软件时的一些技巧和心得。
系统架构与开发环境的差异
用最简单的话来说,Mac OS X与Windows在架构与开发环境上最大的不同点在于:OS X是UNIX也不是UNIX;OS X主要开发工具Xcode使用GCC作为编译程序,与其他种类的UNIX相同;不过OS X也有独树一格的"bundle"软件包装格式这样的东西,成为它与其他操作系统不同之处。
Windows和OS X都属于现代的操作系统,所以Windows在操作系统层级所提供的功能──执行文件与链接库加载、多任务与多线程、内存管理──在OS X上都找得到对等的API和作法。不过,相较于Windows在微软独力开发下,架构和API都维持着相对的一贯性(另一方面,也背负着各种历史遗迹和向 下相容的包袱),Mac OS X则是底层源自NeXTSTEP的Mach微核心(现在称为XNU),而应用层(用准确的UNIX术语来说叫userland)来自FreeBSD 4。这件事情相当重要:OS X透过这样的架构,才拥有和一般Linux/FreeBSD相似的UNIX应用环境。有相当多Mac软件开发者喜欢在UNIX shell下工作,使用各种UNIX工具。在Windows上,必须加装Cygwin之类的环境才能办到。
Apple几年前有则广告是「把其他牌子的UNIX送进/dev/null里」(用过UNIX的朋友应该不 难体会其中的吹嘘意涵)。平心而论,OS X受益自UNIX环境之处不少。尤其,Apple使用了大量的open source工具。举例来说,Apple不像微软,没有自己的C语言编译工具,Apple用的是UNIX业界的标准──open source的GCC(其中当然有不少OS X的扩展功能就是)。虽然Apple有自己的开发环境Xcode,但是底层采用GCC这件事对开发者来说是相当重要的。同时,Apple的C/C++链接 库用的也是GCC标准的stdc/stdc++。了解这个差异,在遇到与Microsoft C/C++ compiler不同的地方时,就更容易能找到解答的资源(这类型问题往往不限于OS X,其他UNIX平台也会发现)。
但是Mac OS X并不完全是UNIX。它的GUI环境(Aqua)就完全不是一般Linux/FreeBSD所使用的X11。而在UNIX层之下的微核心也和其他 UNIX不同。接下来这一点很重要:OS X虽然有和Windows .EXE和.DLL相对应的文件(OS X跟其他UNIX一样,可执行文件一般不加扩展名,UNIX系的动态加载链接库则冠以.dylib),但更重要的架构差异是bundle。
Bundle概念承袭自NeXTSTEP。简单来说,就是由操作系统提供一种类似对象封装的文件包裹。OS X上最常见的bundle要属.app结尾的应用程序了。虽然.app外观上是个文件,在UNIX shell下看就能发现它其实是个目录,内含各种metadata(通常至少会有一个名为Info.plist的数据文件)、可执行文件、动态链接模块、 各种资源等。除了.app外,OS X的各种框架档(以.framework结尾,是一种同时包含头文件及链接库的包装)、应用程序的外挂模块(通常以.bundle结尾)等等,都是以 bundle形式呈现的。了解这个差异,才能了解为什么OS X上很少有程序需要额外的安装程序,也鲜少听说有所谓的"DLL hell"(因共享链接库版本不兼容造成的困扰)。
表一:Windows与Mac OS X在架构上的对照
开发语言与API;Objecitve-C, Core API, Carbon, Cocoa
如果使用微软工具来开发Windows软件,就一定会碰到Platform SDK,MFC或者.Net平台,同时,也相对应到C、C++、C#和其他.Net平台所提供的语言(这种区分并不是绝对的,仅仅是为了方便接下来的模拟 所做的简化)。在OS X上,Apple则是鼓励大家尽量采用Objective-C作为开发语言,并且熟悉Cocoa。
接下来的问题既尴尬又麻烦。很多人会问:我们是否非学Objective-C不可?另外一个常见的问题是:Apple不是也有名叫Carbon的C API吗?(延伸出来的问题则是:可不可以用C++开发Mac程序?)。
简单的答案(同时一定程度上也代表Apple的态度)是:要用Objective-C才能完全发挥OS X图形应用环境的长处,而Cocoa这个用Objective-C写成的API framework就是最佳的施力点。
复杂的答案则是这样:
OS X的本体,也就是所有非UNIX的部份,并不像Windows一开始就(几乎)全以C写成的。因此OS X没有所谓"Win32 API"这么纯粹的东西。OS X核心的、非GUI的服务和链接库,有时称为"Core API"。Core API大部分以C写成,并且多半奠基于CoreFoundation这套链接库之上。CoreFoundation提供了一贯的内存管理模式 (CFRetain, CFRelease)、基础的数据型别(字符串、数组、字典)、property list文件管理、文件、网络存取等等。CoreFoundation使用上跟Win32 API有点相似,都透过存取handle的方式来达到某种近似「用C语言操作对象」的效果。但CoreFoundation最大的不同在于它还有 reference counting的内存管理模式,大幅简化了内存管理的复杂性。
至于Carbon,严格说来,是Mac OS X在发行之初,为了维持与Mac OS 9兼容,才提供一套以C写成的GUI工具集,主要包括所有的GUI组件(Apple 称为 HIToolbox ,HI 意思是 Human Interface)以及所有OS X之前的API(QuickDraw等等)。随着OS X 10.5的推出,Apple渐渐舍弃了旧式的API ,鼓励大家使用Objective-C写成的Cocoa来开发程序。Carbon现在的意义等于就是HIToolbox,也就是OS X GUI 的C API。
但是,Apple在2007年夏天做了重大的宣布;Carbon不会有64-bit的版本。也就是说这一套 C API是「没有未来」的。这意味着所有使用Carbon写成的软件──Microsoft Office、Adobe Photoshop都不可能顺利过渡到64-bit。至于像QT这一类跨平台的GUI kit也势必要顺应这项改变。
其实Objective-C并不难学。由C转换到C++/C#时需要学习很多新观念、新用语,但 Objective-C大体上只是在C语言上加上一层薄薄的、动态的面向对象层。Cocoa则是相当容易上手的API。透过Cocoa就可以用面向对象的 方式存取OS X八成上的系统服务(其余两成可以用C来呼叫)。Objective-C可以跟C完全混用。同时Apple也提供了所谓的"Objective- C++",可以在C++程序中呼叫Objective-C程序,或者在Objective-C里撰写C++程序代码。Apple自家的浏览器Safari 就有不少核心的程序代码(WebKit)使用了Objective-C++来撰写。
表二:开发语言与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在视觉及媒体经验上的核心。
图形作业环境的差异: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等等。这些都是加速开发的好帮 手。
最后要提的是,正因为OS X的文化与Windows有许多不同处,笔者建议跨足OS X的开发者应该要尽可能贴近甚至配合OS X的习惯。举例来说,大多数OS X应用程序都不需要安装程序,只需要直接将软件拷贝到想要存放的目录(通常是/Applications)即可。而解安装也就直接删除该.app bundle就解决了。在Windows上就没那么容易了(特别是有相当多组件依存关系的软件)。这些都是开发上需要注意的地方,但是开发者多付出一份心 力,使用者就会多一份便利,终究会得到用户肯定的。
表三:一些重要的系统特性(摘录)
表四:几个代表性的.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软件的第一步。 >>资源下载
作者介绍
Lukhnos是台灣的Mac開 發者。他是繁體中文輸入法計畫 OpenVanilla的發起人之一,也是該計畫的核心成員。 除了參與多種open source軟體計畫開發外,Lukhnos也是石磐軟體公司 (Lithoglyph Inc.)的創辦人。該公司致力於Mac相關桌面應用軟體 開發並接受開發委託。
大体说来,Windows和Mac OS X都是为桌面应用环境、图形用户接口(GUI)而设计的操作系统。虽然不同平台细节各有特色,但两者相近的抽象概念,其实远远多于相左之处。本文试图指出 方向上明显的异同所在,而非详细列举各种细项差别。最后,我也将简短分享自己在开发跨平台软件时的一些技巧和心得。
系统架构与开发环境的差异
用最简单的话来说,Mac OS X与Windows在架构与开发环境上最大的不同点在于:OS X是UNIX也不是UNIX;OS X主要开发工具Xcode使用GCC作为编译程序,与其他种类的UNIX相同;不过OS X也有独树一格的"bundle"软件包装格式这样的东西,成为它与其他操作系统不同之处。
Windows和OS X都属于现代的操作系统,所以Windows在操作系统层级所提供的功能──执行文件与链接库加载、多任务与多线程、内存管理──在OS X上都找得到对等的API和作法。不过,相较于Windows在微软独力开发下,架构和API都维持着相对的一贯性(另一方面,也背负着各种历史遗迹和向 下相容的包袱),Mac OS X则是底层源自NeXTSTEP的Mach微核心(现在称为XNU),而应用层(用准确的UNIX术语来说叫userland)来自FreeBSD 4。这件事情相当重要:OS X透过这样的架构,才拥有和一般Linux/FreeBSD相似的UNIX应用环境。有相当多Mac软件开发者喜欢在UNIX shell下工作,使用各种UNIX工具。在Windows上,必须加装Cygwin之类的环境才能办到。
Apple几年前有则广告是「把其他牌子的UNIX送进/dev/null里」(用过UNIX的朋友应该不 难体会其中的吹嘘意涵)。平心而论,OS X受益自UNIX环境之处不少。尤其,Apple使用了大量的open source工具。举例来说,Apple不像微软,没有自己的C语言编译工具,Apple用的是UNIX业界的标准──open source的GCC(其中当然有不少OS X的扩展功能就是)。虽然Apple有自己的开发环境Xcode,但是底层采用GCC这件事对开发者来说是相当重要的。同时,Apple的C/C++链接 库用的也是GCC标准的stdc/stdc++。了解这个差异,在遇到与Microsoft C/C++ compiler不同的地方时,就更容易能找到解答的资源(这类型问题往往不限于OS X,其他UNIX平台也会发现)。
但是Mac OS X并不完全是UNIX。它的GUI环境(Aqua)就完全不是一般Linux/FreeBSD所使用的X11。而在UNIX层之下的微核心也和其他 UNIX不同。接下来这一点很重要:OS X虽然有和Windows .EXE和.DLL相对应的文件(OS X跟其他UNIX一样,可执行文件一般不加扩展名,UNIX系的动态加载链接库则冠以.dylib),但更重要的架构差异是bundle。
Bundle概念承袭自NeXTSTEP。简单来说,就是由操作系统提供一种类似对象封装的文件包裹。OS X上最常见的bundle要属.app结尾的应用程序了。虽然.app外观上是个文件,在UNIX shell下看就能发现它其实是个目录,内含各种metadata(通常至少会有一个名为Info.plist的数据文件)、可执行文件、动态链接模块、 各种资源等。除了.app外,OS X的各种框架档(以.framework结尾,是一种同时包含头文件及链接库的包装)、应用程序的外挂模块(通常以.bundle结尾)等等,都是以 bundle形式呈现的。了解这个差异,才能了解为什么OS X上很少有程序需要额外的安装程序,也鲜少听说有所谓的"DLL hell"(因共享链接库版本不兼容造成的困扰)。
表一:Windows与Mac OS X在架构上的对照
开发语言与API;Objecitve-C, Core API, Carbon, Cocoa
如果使用微软工具来开发Windows软件,就一定会碰到Platform SDK,MFC或者.Net平台,同时,也相对应到C、C++、C#和其他.Net平台所提供的语言(这种区分并不是绝对的,仅仅是为了方便接下来的模拟 所做的简化)。在OS X上,Apple则是鼓励大家尽量采用Objective-C作为开发语言,并且熟悉Cocoa。
接下来的问题既尴尬又麻烦。很多人会问:我们是否非学Objective-C不可?另外一个常见的问题是:Apple不是也有名叫Carbon的C API吗?(延伸出来的问题则是:可不可以用C++开发Mac程序?)。
简单的答案(同时一定程度上也代表Apple的态度)是:要用Objective-C才能完全发挥OS X图形应用环境的长处,而Cocoa这个用Objective-C写成的API framework就是最佳的施力点。
复杂的答案则是这样:
OS X的本体,也就是所有非UNIX的部份,并不像Windows一开始就(几乎)全以C写成的。因此OS X没有所谓"Win32 API"这么纯粹的东西。OS X核心的、非GUI的服务和链接库,有时称为"Core API"。Core API大部分以C写成,并且多半奠基于CoreFoundation这套链接库之上。CoreFoundation提供了一贯的内存管理模式 (CFRetain, CFRelease)、基础的数据型别(字符串、数组、字典)、property list文件管理、文件、网络存取等等。CoreFoundation使用上跟Win32 API有点相似,都透过存取handle的方式来达到某种近似「用C语言操作对象」的效果。但CoreFoundation最大的不同在于它还有 reference counting的内存管理模式,大幅简化了内存管理的复杂性。
至于Carbon,严格说来,是Mac OS X在发行之初,为了维持与Mac OS 9兼容,才提供一套以C写成的GUI工具集,主要包括所有的GUI组件(Apple 称为 HIToolbox ,HI 意思是 Human Interface)以及所有OS X之前的API(QuickDraw等等)。随着OS X 10.5的推出,Apple渐渐舍弃了旧式的API ,鼓励大家使用Objective-C写成的Cocoa来开发程序。Carbon现在的意义等于就是HIToolbox,也就是OS X GUI 的C API。
但是,Apple在2007年夏天做了重大的宣布;Carbon不会有64-bit的版本。也就是说这一套 C API是「没有未来」的。这意味着所有使用Carbon写成的软件──Microsoft Office、Adobe Photoshop都不可能顺利过渡到64-bit。至于像QT这一类跨平台的GUI kit也势必要顺应这项改变。
其实Objective-C并不难学。由C转换到C++/C#时需要学习很多新观念、新用语,但 Objective-C大体上只是在C语言上加上一层薄薄的、动态的面向对象层。Cocoa则是相当容易上手的API。透过Cocoa就可以用面向对象的 方式存取OS X八成上的系统服务(其余两成可以用C来呼叫)。Objective-C可以跟C完全混用。同时Apple也提供了所谓的"Objective- C++",可以在C++程序中呼叫Objective-C程序,或者在Objective-C里撰写C++程序代码。Apple自家的浏览器Safari 就有不少核心的程序代码(WebKit)使用了Objective-C++来撰写。
表二:开发语言与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在视觉及媒体经验上的核心。
图形作业环境的差异: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等等。这些都是加速开发的好帮 手。
最后要提的是,正因为OS X的文化与Windows有许多不同处,笔者建议跨足OS X的开发者应该要尽可能贴近甚至配合OS X的习惯。举例来说,大多数OS X应用程序都不需要安装程序,只需要直接将软件拷贝到想要存放的目录(通常是/Applications)即可。而解安装也就直接删除该.app bundle就解决了。在Windows上就没那么容易了(特别是有相当多组件依存关系的软件)。这些都是开发上需要注意的地方,但是开发者多付出一份心 力,使用者就会多一份便利,终究会得到用户肯定的。
表三:一些重要的系统特性(摘录)
表四:几个代表性的.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软件的第一步。 >>资源下载
作者介绍
Lukhnos是台灣的Mac開 發者。他是繁體中文輸入法計畫 OpenVanilla的發起人之一,也是該計畫的核心成員。 除了參與多種open source軟體計畫開發外,Lukhnos也是石磐軟體公司 (Lithoglyph Inc.)的創辦人。該公司致力於Mac相關桌面應用軟體 開發並接受開發委託。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
他的文章
谁下载
ycloud
zxc
lesboy
coolboylmk
HLTV
you8107
dalao
cccaaa123
zhaosili
pmma
warcraft
nnhehe
liyebin
xiaogozaijiao
lsuper
ycool
爬爬狗
inraining
Intelfan
heihu
FirefoxXP
gbmf
wdscxsj
yzwyq
cntrump
xfhsm
Netangle
better
kpld
eyeye
aaronqlm
tinyant
nevergone
nasiriyan
youmikoo
xwyyn
SongLei
yangxdyxdh
flyblue
wenkaidu
loqich
exile
cshcmq
CCDeath
sunnelson
JohnsonGuo
黄sir
kxltzczh
diybl
tonyjou
noid
晕菜菜
Callppsb
xxyyzasabc
dungthuan
tiany
denglifeng
xiaojinge
破北
h旋风h
acquo
aiie
winddyj
apcwowo
BMZYNX
sllssy
lyricC
teresalx
sybupt
imbadyc
古越魂
virusest
cxxxx
coltor
openaxot
石全
dbcoo
qiaoqiaota
joeyye
kennshi
成惜
meakhella
cooseasy
yoursmile
hidoom
犯錯
rakehellj
xtester
huanggai
Oefvode
shuax
hahadazu
巴别塔
叛逆者
wansichao
空山
还真以为
cvbnmT
masonghai
谁下载
ycloud
zxc
lesboy
coolboylmk
HLTV
you8107
dalao
cccaaa123
zhaosili
pmma
warcraft
nnhehe
liyebin
xiaogozaijiao
lsuper
ycool
爬爬狗
inraining
Intelfan
heihu
FirefoxXP
gbmf
wdscxsj
yzwyq
cntrump
xfhsm
Netangle
better
kpld
eyeye
aaronqlm
tinyant
nevergone
nasiriyan
youmikoo
xwyyn
SongLei
yangxdyxdh
flyblue
wenkaidu
loqich
exile
cshcmq
CCDeath
sunnelson
JohnsonGuo
黄sir
kxltzczh
diybl
tonyjou
noid
晕菜菜
Callppsb
xxyyzasabc
dungthuan
tiany
denglifeng
xiaojinge
破北
h旋风h
acquo
aiie
winddyj
apcwowo
BMZYNX
sllssy
lyricC
teresalx
sybupt
imbadyc
古越魂
virusest
cxxxx
coltor
openaxot
石全
dbcoo
qiaoqiaota
joeyye
kennshi
成惜
meakhella
cooseasy
yoursmile
hidoom
犯錯
rakehellj
xtester
huanggai
Oefvode
shuax
hahadazu
巴别塔
叛逆者
wansichao
空山
还真以为
cvbnmT
masonghai
谁下载
ycloud
zxc
lesboy
coolboylmk
HLTV
you8107
dalao
cccaaa123
zhaosili
pmma
warcraft
nnhehe
liyebin
xiaogozaijiao
lsuper
ycool
爬爬狗
inraining
Intelfan
heihu
FirefoxXP
gbmf
wdscxsj
yzwyq
cntrump
xfhsm
Netangle
better
kpld
eyeye
aaronqlm
tinyant
nasiriyan
youmikoo
xwyyn
SongLei
yangxdyxdh
flyblue
wenkaidu
loqich
exile
cshcmq
CCDeath
sunnelson
JohnsonGuo
黄sir
kxltzczh
diybl
tonyjou
noid
晕菜菜
Callppsb
xxyyzasabc
dungthuan
tiany
denglifeng
xiaojinge
破北
h旋风h
acquo
aiie
winddyj
apcwowo
BMZYNX
sllssy
lyricC
teresalx
sybupt
imbadyc
古越魂
virusest
cxxxx
coltor
openaxot
石全
dbcoo
qiaoqiaota
joeyye
kennshi
成惜
meakhella
cooseasy
yoursmile
hidoom
犯錯
rakehellj
xtester
huanggai
Oefvode
shuax
hahadazu
巴别塔
叛逆者
wansichao
空山
还真以为
cvbnmT
masonghai
guetx
谁下载
ycloud
zxc
lesboy
coolboylmk
HLTV
you8107
dalao
cccaaa123
zhaosili
pmma
warcraft
nnhehe
liyebin
xiaogozaijiao
lsuper
ycool
爬爬狗
inraining
Intelfan
heihu
FirefoxXP
gbmf
wdscxsj
yzwyq
cntrump
xfhsm
Netangle
better
kpld
eyeye
aaronqlm
tinyant
nevergone
nasiriyan
youmikoo
xwyyn
SongLei
yangxdyxdh
flyblue
wenkaidu
loqich
exile
cshcmq
CCDeath
sunnelson
JohnsonGuo
黄sir
kxltzczh
diybl
tonyjou
noid
晕菜菜
Callppsb
xxyyzasabc
dungthuan
tiany
denglifeng
xiaojinge
破北
h旋风h
acquo
aiie
winddyj
apcwowo
BMZYNX
sllssy
lyricC
teresalx
sybupt
imbadyc
古越魂
virusest
cxxxx
coltor
openaxot
石全
dbcoo
qiaoqiaota
joeyye
kennshi
成惜
meakhella
cooseasy
yoursmile
hidoom
犯錯
rakehellj
xtester
huanggai
Oefvode
shuax
hahadazu
巴别塔
叛逆者
wansichao
空山
还真以为
cvbnmT
masonghai
看原图
赞赏
雪币:
留言: