转载:http://blog.sina.com.cn/s/blog_4ca9ceef01011ggq.html
国际化您的应用程序
理想情况下,iPhone应用程序显示给用户的文本、图像、和其它内容都应该本地化为多种语言。比如,警告对话框中显示的文本就应该以用户偏好的语言显示。为工程准备特定语言的本地化内容的过程就称为国际化。工程中需要本地化的候选组件包括:
§
§
§
§
§
通过Settings程序,用户可以从Language偏好设置视图(参见图1-8)中选择希望在用户界面上看到的语言。您可以访问General设置,然后在International组中找到该视图。
用户选择的语言和程序包中的一个子目录相关联,该子目录名由两个部分组成,分别是ISO 639-1定义的语言码和.lproj
后缀。您还可以对语言码进行修改,使之包含具体的地区,方法是在后面(在下划线之后)加入ISO 3166-1定义的区域指示符。举例来说,如果要指定美国英语的本地化资源,程序包中的子目录应该命名为en_US.lproj
。我们约定,本地化语言子目录称为lproj
文件夹。
请注意:您也可以使用ISO 639-2语言码,而不一定使用ISO 639-1的定义。有关语言和区域代码的信息,请参见国际化编程主题文档中的“语言和地域的指定”部分。
一个lproj
文件夹中包含所有指定语言(还可能包含指定地区)的本地化内容。您可以用NSBundle
类或CFBundleRef
封装类型提供的工具来(在应用程序的lproj
文件夹)定位当前选定语言的本地化资源。列表1-3给出一个包含英语(en
)本地化内容的目录。
en.lproj/ |
|
|
|
这个例子目录有下面几个项目:
§ InfoPlist.strings
文件,包含与Info.plist
文件中特定键(比如CFBundleDisplayName
)相关联的本地化字符串值。比如,一个英文名称为Battleship的应用程序,其CFBundleDisplayName
键在fr.lproj
子目录的InfoPlist.strings
文件中有如下的入口:
CFBundleDisplayName = "Cuirassé"; |
§ Localizable.strings
文件,包含应用程序代码生成的字符串的本地化版本。
§ sign.png
,是一个包含本地化图像的文件。
为了本地化,我们需要国际化代码中的字符串,具体做法是用NSLocalizedString
宏来代替字符串。这个宏的定义如下:
NSString *NSLocalizedString(NSString *key, NSString *comment); |
第一个参数是一个唯一的键,指向给定lproj
文件夹中Localizable.strings
文件里的一个本地化字符串;第二个参数是一个注释,说明字符串如何使用,因此可以为翻译人员提供额外的上下文。举例来说,假定您正在设置用户界面中一个标签(UILabel
对象)的内容,则下面的代码可以国际化该标签的文本:
label.text = NSLocalizedString(@"City", @"Label for City text field"); |
然后,您就可以为给定语言创建一个Localizable.strings
文件,并将它加入到相应的lproj
文件夹中。对于上文例子中的键,该文件中应该有如下入口:
"City" = "Ville"; |
请注意:另一种方法是在代码中恰当的地方插入NSLocalizedString
调用,然后运行genstrings
命令行工具。该工具会生成一个Localizable.strings
文件的模板,包含每个需要翻译的键和注释。更多有关genstrings
的信息,请参见genstrings(1)
的man页面。
更多有关国际化的信息,请参见国际化编程主题。
在应用程序开发过程的每一步,您都应该考虑自己所做的设计对应用程序总体性能的影响。由于iPhone和iPod touch设备的移动本质,iPhone应用程序的操作环境受到更多的限制。本文的下面部分将描述在开发过程中应该考虑哪些因素。
不要阻塞主线程
您应该认真考虑在应用程序主线程上执行的任务。主线程是应用程序处理触摸事件和其它用户输入的地方。为了确保应用程序总是可以响应用户,我们不应该在主线程中执行运行时间很长或可能无限等待的任务,比如访问网络的任务。相反,您应该将这些任务放在后台线程。一个推荐的方法是将每个任务都封装在一个操作对象中,然后加入操作队列。当然,您也可以自己创建显式的线程。
将任务转移到后台可以使您的主线程继续处理用户输入,这对于应用程序的启动和退出尤其重要。在这些时候,系统期望您的应用程序及时响应事件。如果应用程序的主线程在启动过程中被阻塞住了,系统甚至可能在启动完成之前将它杀死;如果主线程在退出时被阻塞了,则应用程序可能来不及保存关键用户数据就被杀死了。
更多有关如何使用操作对象和线程的信息,请参见线程编程指南。
有效地使用内存
由于iPhone OS的虚存模型并不包含磁盘交换区空间,所以应用程序在更大程度上受限于可供使用的内存。对内存的大量使用会严重降低系统的性能,可能导致应用程序被终止。因此,在设计阶段,您应该把减少应用程序的内存开销放在较高优先级上。
应用程序的可用内存和相对性能之间有直接的联系。可用内存越少,系统在处理未来的内存请求时就越可能出问题。如果发生这种情况,系统总是先把代码页和其它非易失性资源从内存中移除。但是,这可能只是暂时的修复,特别是当系统在短时间后又再次需要那些资源的时候。相反,您需要尽可能使内存开销最小化,并及时清除自己使用的内存。
本文的下面部分将就如何有效使用内存和在只有少量内存时如何反应方面提供更多的指导。
减少应用程序的内存印迹
表1-7列出一些如何减少应用程序总体内存印迹的技巧。在开始时将内存印迹降低了,随后就可以有更多的空间用于需要操作的数据。
技巧 | 采取的措施 |
消除内存泄露 | 由于内存是iPhoneOS的关键资源,所以您的应用程序不应该有任何的内存泄露。存在内存泄露意味着应用程序在之后可能没有足够的内存。您可以用Instruments程序来跟踪代码中的泄露,该程序既可以用于仿真器,也可以用于实际的设备。有关如何使用Instruments的更多信息,请参见Instruments用户指南。 |
使资源文件尽可能小 | 文件驻留在磁盘中,但在使用时需要载入内存。属性列表文件和图像文件是通过简单的处理就可以节省空间的两种资源类型。您可以通过 |
使用CoreData | 如果您的应用程序需要操作大量的结构化数据,请将它存储在CoreData的持久存储或SQLite数据库,而不是使用扁平文件。CoreData和SQLite都提供了管理大量数据的有效方法,不需要将整个数据一次性地载入内存。 Core Data的支持是在iPhone OS 3.0系统上引入的。 |
延缓装载资源 | 在真正需要资源文件之前,永远不应该进行装载。预先载入资源文件表面看好象可以节省时间,但实际上会使应用程序很快变慢。此外,如果您最终没有用到那些资源,预先载入将只是浪费内存。 |
将程序连编为Thumb格式 | 加入 |
恰当地分配内存
iPhone应用程序使用委托内存模式,因此,您必须显式保持和释放内存。表1-8列出了一些在程序中分配内存的技巧。
技巧 | 采取的措施 |
减少自动释放对象的使用 | 通过 |
为资源设置尺寸限制 | 避免装载大的资源文件,如果有更小的文件可用的话。请用适合于iPhoneOS设备的恰当尺寸图像来代替高清晰度的图像。如果您必须使用大的资源文件,需要考虑仅装载当前需要的部分。举例来说,您可以通过 |
避免无边界的问题集 | 无边界的问题集可能需要计算任意大量的数据。如果该集合需要的内存比当前系统能提供的还要多,则您的应用程序可能无法进行计算。您的应用程序应该尽可能避免处理这样的集合,而将它们转化为内存使用极限已知的问题。 |
有关如何在iPhone应用程序中分配内存及使用自动释放池的详细信息,请参见Cocoa基本原理指南文档的Cocoa对象部分。
浮点数学运算的考虑
iPhone–OS设备上的处理器有能力在硬件上处理浮点数计算。如果您目前的程序使用基于软件的定点数数学库进行计算,则应该考虑对代码进行修改,转向使用浮点数数学库。典型情况下,基于硬件的浮点数计算比对应的基于软件的定点数计算快得多。
重要提示:当然,如果您的代码确实广泛地使用浮点数计算,请记住不要使用-mthumb
选项来编译代码。Thumb选项可以减少代码模块的尺寸,但是也会降低浮点计算代码的性能。
减少电力消耗
移动设备的电力消耗一直是个问题。iPhone OS的电能管理系统保持电能的方法是关闭当前未被使用的硬件功能。此外,要避免CPU密集型和高图形帧率的操作。您可以通过优化如下组件的使用来提高电池的寿命:
§
§
§
§
§
您的优化目标应该是以尽可能有效的方式完成大多数的工作。您应该总是采用Instruments和Shark工具对应用程序的算法进行优化。但是,很重要的一点是,即使最优化的算法也可能对设备的电池寿命造成负面的影响。因此,在写代码的时候应该考虑如下的原则:
§ NSRunLoop
或者NSTimer
类来规划需要做的工作,而不是使用轮询。
§ UIApplication
对象的idleTimerDisabled
属性值保持为NO
。当设备处于不活动状态一段时间后,空闲定时器会关闭设备的屏幕。如果您的应用程序不需要设备屏幕保持打开状态,就让系统将它关闭。如果关闭屏幕给您的应用程序的体验带来负面影响,则需要通过修改代码来消除那些影响,而不是不必要地关闭空闲定时器。
§
§
§
§ UIAccelerometer
类来接收常规的加速计事件,则当您不再需要那些事件时,要禁止这些事件。类似地,请将事件传送的频率设置为满足应用程序需要的最小值。更多信息请参见“访问加速计事件”部分。
您向网络传递的数据越多,就需要越多的电能来进行无线发射。事实上,访问网络是您所能进行的最耗电的操作,您应该遵循下面的原则,使网络访问最小化:
§
§
§
§
§
代码的优化
和iPhone OS一起推出的还有几个应用程序的优化工具。它们中的大部分都运行在Mac OS X上,适合于调整运行在仿真器上的代码的某些方面。举例来说,您可以通过仿真器来消除内存泄露,确保总的内存开销尽可能小。借助这些工具,您还可以排除代码中可能由低效算法或已知瓶颈引起的计算热点。
在仿真器上进行代码优化之后,还应该在设备上用Instruments程序进行进一步优化。在实际设备上运行代码是对其进行完全优化的唯一方式。因为仿真器运行在Mac OS X上,而运行Mac OS X的系统具有更快的CPU和更多的可用内存,所以其性能通常比实际设备的性能好很多。在实际设备上用Instruments跟踪代码可能会发现额外的性能瓶颈,您需要进行优化。
更多有关 Instruments 的使用信息,请参见 Instruments用户指南