预计应用程序行为
每个新的Xcode项目都配置为在iOS模拟器或设备上运行。但是仅仅能够在设备上运行并不意味着你的应用程序可以在app Store上发布。每个应用程序都需要一定数量的定制,以确保用户有良好的体验。自定义可以从提供应用程序的图标到为应用程序如何显示和使用信息做出架构级的决定。这一章描述了所有应用程序都应该处理的行为,并且在规划过程中应该尽早考虑。
Providing the Required Resources 提供所需的资源
您创建的每个应用程序都必须拥有以下资源和元数据集,以便在iOS设备上正确显示:
An information property-list file. 一个信息属性列表文件。 Info.plist 文件包含您的应用程序的元数据,系统使用它与您的应用程序进行交互。Xcode根据您的项目的配置和设置自动为您创建这个文件。如果您想要直接查看或修改该文件的内容,您可以从项目的Info选项卡中完成。有关编辑此文件的信息,以及关于您应该包括哪些 key 的建议,参考 The Information Property List File.
A declaration of the app’s required capabilities. 应用程序所需功能的声明。每个应用程序必须声明它需要运行的硬件功能或特性。应用程序商店使用这些信息来确定用户是否可以在特定设备上运行你的应用程序。您可以在项目的Info选项卡中使用所需的设备功能条目来编辑应用程序的需求列表。有关如何配置此 key 的信息, 参考 Declaring the Required Device Capabilities.
One or more icons. 一个或多个图标。该系统在用户设备的主屏幕上显示你的应用程序图标。该系统还可以在设置app中使用其他版本的图标,或者在显示搜索结果时使用。有关如何指定应用程序图标的信息,请参考 App Icons.
One or more launch images. 一个或多个发射图像。当应用程序启动时,系统会显示一个临时图像,直到应用程序能够显示它的用户界面。这个临时图像是你的应用程序的启动图像,它为用户提供你的应用正在启动的即时反馈,并且很快就会准备好。您必须为您的应用程序提供至少一个启动映像,您可以提供额外的启动映像以解决特定的场景。有关创建发射映像的信息, 请参考 App Launch (Default) Images.
所有的应用都需要这些资源,但不是唯一的。在你的应用程序的信息中,有很多的key是Xcode不包含的。plist文件默认情况下。大部分的额外key很重要,只有你特定的功能合并到应用程序。例如,一个应用程序使用麦克风应该包括NSMicrophoneUsageDescription关键信息,为用户提供应用程序打算如何使用它
Bundle
bundle是文件系统中的一个目录,该目录将可执行代码和相关资源(如图像和声音)放在一个地方。在iOS和OS X中,应用程序、框架、插件和其他类型的软件都是捆绑的。bundle是一个具有标准化层次结构的目录,它包含代码所使用的可执行代码和资源。Foundation和Core Foundation包括用于定位和装载代码和包中的资源的设施。
Note: 应用程序是第三方开发者可以在iOS上创建的唯一类型的bundle。
bundle给用户和开发者带来了一些好处。通过简单地将应用程序从一个位置移动到另一个位置,它们使安装或迁移应用程序或其他软件变得容易。bundle也是国际化的一个重要因素。您将本地化资源存储在一个包的特别命名的子目录中;编程工具寻找与用户的语言首选项相对应的位置的本地化资源。
当您构建可执行文件时,大多数类型的Xcode项目都会为您创建一个bundle。因此,您很少需要手工构建一个bundle。即便如此,了解它们的结构以及如何访问它们内部的代码和资源也是非常重要的。
Structure and Content of Bundles bundle的结构和内容
bundle可以包含可执行代码、图像、声音、nib文件、私有框架和库、插件、可加载包或任何其他类型的代码或资源。它还包含一个名为information property list (Info.plist)的运行时配置文件。每一项都在bundle结构中有适当的位置。资源(如图像、声音和nib文件)存储在资源子目录中。它们可以是本地化的,也可以是非本地化的。本地化文件(包括字符串文件,它们是本地化字符串的集合)被放在资源的子目录中,这些子目录具有lproj的扩展名和与语言和可能的语言环境相对应的名称。
Accessing Bundle Resources 访问bundle资源
每个应用程序都有一个主包,即包含应用程序代码的包。当用户启动一个应用程序时,它会发现它立即需要的主包中的代码和资源,并将其加载到内存中。此后,应用程序可以根据需要动态地(和延迟地)从主包或从属包中加载代码和资源。
NSBundle 类,对于过程代码,CFBundleRef 不透明类型的Core Foundation为您的应用程序提供了在bundle中定位资源的方法。在Objective-C中,首先必须获得一个与物理包对应的NSBundle实例。要获得应用程序的主包,请调用类方法mainBundle。当给定一个文件名、扩展名和(可选地)一个bundle子目录时,其他NSBundle方法返回路径来绑定资源。在找到资源的路径之后,可以使用适当的类将其加载到内存中。
Loadable Bundles 可加载的包
与应用程序包一样,可加载的bundle包可执行代码和相关资源,但您在运行时显式加载这些包。您可以使用可加载的包来设计高度模块化、可定制和可扩展的应用程序。每个可加载的包都有一个主类,它是bundle的入口点;当您加载这个包时,您必须向主类请求NSBundle,并使用返回的类对象创建类的实例。
The App Bundle
当您构建您的iOS应用程序时,Xcode将它打包成一个包。bundle是文件系统中的一个目录,将相关的资源集中在一个地方。iOS应用程序包包含应用程序可执行文件和支持资源文件,如应用程序图标、图像文件和本地化内容。表1-1列出了一个典型的iOS应用程序包的内容,用于演示目的是MyApp。本例仅用于说明目的。此表中列出的一些文件可能不会出现在您自己的应用程序包中。
Table 1-1 A typical app bundle
File | Example | Description |
---|---|---|
App executable | MyApp | 可执行文件包含您的应用程序的编译代码。 你的应用程序的可执行文件的名称与你的应用程序名称- .app扩展名相同。 这个文件是必需的。 |
The information property list file | Info.plist | Info。plist文件包含应用程序的配置数据,系统使用这些数据来决定如何与应用程序交互。 该文件是必需的,必须称为Info.plist。有关更多信息,请参见信息属性列表文件。 |
App icons | Icon.png [email protected] Icon-Small.png [email protected] |
你的应用程序图标用来在设备的主屏幕上代表你的应用程序。系统在适当的地方使用其他图标。 在文件名中带有@2x的图标用于显示视网膜显示屏的设备。 需要一个应用图标。有关指定图标图像文件的信息,请参见应用程序图标。 |
Launch images | Default.png Default-Portrait.png Default-Landscape.png |
当你的应用程序启动时,系统将此文件作为临时背景。 一旦你的应用程序准备好显示它的用户界面,它就会被删除。 至少需要一个发射图像。 有关指定发射图像的信息,请参见应用程序启动(默认)图像。 |
Storyboard files (or nib files) | MainBoard.storyboard | 故事板包含应用程序在屏幕上显示的视图和视图控制器。 故事板中的视图是根据呈现它们的视图控制器组织的。 故事板还标识将用户从一组视图切换到另一组视图的转换(称为segue)。 在创建项目时,由Xcode设置主故事板文件的名称。您可以通过为info.plist 信息中的 UIMainStoryboardFile 键指定一个不同的值来更改名称。 使用nib文件而不是故事板的应用程序可以用NSMainNibFile键替换UIMainStoryboardFile键,并使用该密钥指定它们的主nib文件。 故事板(或nib文件)的使用是可选的,但推荐使用。 |
Ad hoc distribution icon | iTunesArtwork | 如果你正在分配你的应用程序,包括一个512 x 512像素版本的应用程序图标。 这个图标通常由App Store提供,从你提交到iTunes Connect的材料。 然而,由于应用程序是不经过应用程序商店的,所以你的图标必须出现在你的应用程序包里。 iTunes使用这个图标来代表你的应用程序(你指定的文件应该是你提交给应用程序商店的那个文件,如果你是这样分配你的应用程序的话)。 此图标的文件名必须是iTunesArtwork,不能包含文件名扩展名。 这个文件是临时分发的,但除此之外是可选的。 |
Settings bundle | Settings.bundle | 如果您想通过设置应用程序公开自定义应用程序首选项,您必须包含一个Settings bundle。 这个bundle包含属性列表数据和定义应用程序首选项的其他资源文件。 Settings应用程序使用这个包中的信息来组装应用程序所需的接口元素。 这个包是可选的。 有关首选项和指定设置包的更多信息,请参见首选项和设置编程指南。 |
Nonlocalized resource files | sun.png mydata.plist |
非本地化资源包括图像、声音文件、电影和应用程序使用的自定义数据文件。所有这些文件都应该放在应用程序包的顶层。 |
Subdirectories for localized resources | en.lproj fr.lproj es.lproj |
本地化资源必须放置在特定于语言的项目目录中,其中的名称由ISO 639-1语言缩写加上.lproj后缀组成。(例如,en。lproj、fr.lproj和es。lproj目录包含英语、法语和西班牙语本地化的资源。一个iOS应用程序应该国际化,并有一种语言。lproj目录,用于支持的每种语言。除了提供应用程序的定制资源的本地化版本之外,还可以通过在特定于语言的项目目录中放置同名的文件来本地化应用程序图标、启动图像和设置图标。有关更多信息,请参见国际化应用程序。 |
注意:iOS应用程序bundle不能包含名为“Resources”的自定义目录
有关iOS应用程序包结构的更多信息,请参见Bundle Programming Guide。有关如何从bundle中加载资源文件的信息,请参阅Resource Programming Guide。
信息属性列表文件 info.plist
Xcode使用您的项目的一般、功能和信息选项卡的信息,在编译时为应用程序生成一个信息属性列表(Info.plist)文件。Info.plist文件是一个结构化文件,包含关于应用程序配置的关键信息。应用程序商店和iOS使用它来确定你的应用程序的功能和定位关键资源。每个应用程序都必须包含这个文件。
尽管Xcode提供的info.plist文件包含所有必需条目的默认值,大多数应用程序需要一些更改或添加。只要有可能,使用通用和功能选项卡来指定应用程序的配置信息。如果在这些选项卡中没有看到特定选项,请使用Info选项卡。
对于Xcode不提供定制配置接口的选项,您必须使用Xcode属性列表编辑器直接提供适当的键和值。Info选项卡的自定义iOS目标属性部分包含要包含在信息中的条目的摘要。plist文件。默认情况下,Xcode显示了人们可读的对预期特性的描述,但是每个特性实际上对应于info.plist文件中的唯一键。大多数密钥都是可选的,并且很少使用,但是在定义任何新项目时,您应该考虑一些关键因素:
在Info选项卡中声明应用程序的所需功能
所需的设备功能部分包含关于应用程序需要运行的设备级特性的信息。应用程序商店使用这个条目中的信息来确定你的应用程序的功能,并防止它被安装在不支持你的应用需要的功能的设备上。有关更多信息,请参见声 明所需的设备功能。需要持久Wi-Fi连接的应用程序必须声明这个因素
如果你的应用程序与网络上的服务器对话,你可以添加应用程序使用Wi-Fi进入你的项目的Info标签。该条目对应于Info.plist文件中的UIRequiresPersistentWiFi key。设置此键可以防止iOS在长时间不活动时关闭活动的Wi-Fi连接。建议所有使用该网络与服务器通信的应用程序声明此key。报刊亭应用程序必须声明自己是这样的
包括UINewsstandApp key,表明你的应用程序从报摊应用程序中显示内容。
定义自定义文档类型的应用程序必须声明这些类型
使用Info选项卡的文档类型部分为您支持的文档格式指定图标和UTI信息。系统使用这些信息来识别能够处理特定文件类型的应用程序。有关向应用程序添加文档支持的更多信息,请参见基于文档的iOS应用程序编程指南。应用程序可以声明他们支持的任何自定义URL计划
使用Info选项卡的URL类型部分来指定应用程序处理的自定义URL计划。应用程序可以使用自定义的URL方案进行通信。有关如何实现对该特性的支持的更多信息,请参见使用URL方案与应用程序通信。应用程序必须提供用于访问用户数据和某些应用程序特性的目的字符串(有时称为“使用描述”)
当涉及到应用程序访问用户数据或设备功能的隐私问题时,iOS会提示用户并请求用户允许。应用程序必须通过在其info.plist文件中定义的目的字符串向用户解释,为什么它需要访问。如果您的应用程序试图在没有提供相应的目的字符串的情况下获得访问,那么您的应用程序就会退出。
表1-2描述了需要用户权限的数据和特性。目的字符串在信息属性列表的Cocoa Keys章节中被描述。
声明所需的设备功能
所有应用程序必须声明它们需要运行的设备特定功能。Xcode在项目的Info选项卡中包含一个必需的设备功能条目,并以一些最低要求填充它。您可以为该条目添加值,以指定应用程序所需的额外需求info.plist文件。
UIRequiredDeviceCapabilities 键的值是一个数组或字典,其中包含你的应用需要的附加的键识别功能(或具体禁止)。如果您使用数组指定键的值,则键的存在说明该特性是必需的;缺少密钥表明该特性不是必需的,并且该应用程序可以在没有它的情况下运行。如果您指定了一个字典,那么字典中的每个键都必须具有一个布尔值,该值指示该特性是必需的还是被禁止的。true的值表示该特性是必需的,而false表示该特性不能出现在设备上。如果你的应用程序是可选的,那就不要在字典里包含相应的键。
有关您可以为UIRequiredDeviceCapabilities 键包括的值的详细信息,请参见 信息属性列表的key引用。
App Icons
每个应用程序都必须提供一个图标,显示在设备的主屏幕和应用程序商店中。一个应用程序可以在不同的情况下指定几个不同的图标。例如,一个应用程序可以在显示搜索结果时提供一个小图标,并且可以为视网膜显示屏的设备提供高分辨率的图标。
新的Xcode项目包括应用程序图标图像的图像资产项。若要添加图标,请将相应的图像文件分配给项目的图像资产。在构建时,Xcode为应用程序的info.plist文件添加适当的键,并将图像放在应用程序包中。
有关设计应用程序图标的信息,包括这些图标的大小,请参见iOS人机界面指南。
App Launch (Default) Images
当系统首次在设备上启动应用程序时,它会在屏幕上临时显示一个静态启动图像。这是你的应用程序的启动图像,它是你在Xcode项目中指定的资源。启动图像为用户提供即时反馈,你的应用程序已经启动,同时给你的应用程序时间准备它的初始用户界面。当您的应用程序的窗口被配置并准备好显示时,系统就会切换到该窗口的启动映像。
当你的应用程序的用户界面最近的快照可用时,系统更倾向于使用该图像而不是使用你的应用程序的启动图像。当应用程序从前台切换到后台时,系统会对应用程序的用户界面进行快照。当你的应用程序返回到前台时,它会在可能的情况下使用该图像而不是发射图像。如果用户已经杀死了你的应用程序,或者你的应用程序没有运行很长时间,系统会丢弃快照,并再次依赖于你的发射图像。
新的Xcode项目包括应用程序启动图像的图像资产项。要添加启动图像,请将相应的图像文件添加到项目的映像资产中。在构建时,Xcode为应用程序的info.plist文件添加适当的键,并将图像放在应用程序包中。
有关设计你的应用程序的发布图像的信息,包括这些图片的大小,请参见iOS人机界面指南。
支持用户隐私
为用户隐私设计是很重要的。大多数iOS设备都包含用户可能不想向应用程序或外部实体公开的个人数据。如果你的应用程序不适当地访问或使用数据,用户可能会删除你的应用程序。
仅凭用户的知情同意获取用户或设备数据。此外,采取适当的步骤保护用户和设备数据,并对如何使用它保持透明。以下是一些你可以采取的最佳做法:
- 这些报告为保护用户隐私提供了有益的建议。你也应该和公司的法律顾问一起审查这些文件。
联邦贸易委员会关于移动隐私的报告:
Mobile Privacy Disclosures: Building Trust Through Transparency.
欧盟数据保护专员对移动应用数据保护的意见:http://ec.europa.eu/justice/data-protection/article-29/documentation/opinion-recommendation/files/2013/wp202_en.pdf
日本内务和通信部的智能手机隐私倡议:
智能手机隐私倡议(2012):
http://www.soumu.go.jp/main_sosiki/joho_tsusin/eng/presentation/pdf/Initiative.pdf
智能手机隐私倡议II (2013):
http://www.soumu.go.jp/main_sosiki/joho_tsusin/eng/presentation/pdf/Summary_II.pdf
- 请求访问敏感用户或设备数据,这是受iOS系统授权设置保护的,此时应用程序需要数据。您必须在应用程序的信息中提供一个目的字符串(有时称为使用描述字符串)。plist文件解释为什么你的应用程序需要你试图访问的数据或资源。由iOS系统授权设置保护的数据包括位置、联系人、日历事件、提醒、照片、媒体和其他许多类型;见表1 - 2。在用户不允许访问所请求的数据的情况下提供合理的回退行为。
对用户公开他们的数据如何使用是透明的。例如,当你将你的应用程序提交到应用程序商店时,为你的隐私政策或声明指定一个URL作为你的iTunes Connect元数据的一部分。您可能还需要在应用程序描述中总结该策略或语句。
让用户控制他们的用户或设备数据。提供设置,以便用户可以根据需要禁用对特定类型的敏感信息的访问。
请求和使用完成给定任务所需的最少用户或设备数据。不要因为不必要的原因,或因为你认为以后可能有用的原因而寻求访问或收集数据。
采取合理的步骤来保护你在应用程序中收集的用户和设备数据。在本地存储这些信息时,尝试使用iOS数据保护功能(使用磁盘加密保护数据)以加密的格式存储。当通过网络发送用户或设备数据时,使用应用程序传输安全性(如在NSAppTransportSecurity中所描述的)。
如果你的应用程序使用ASIdentifierManager类,你必须尊重它的广告跟踪功能属性的价值。如果该属性被用户设置为NO,那么使用ASIdentifierManager类仅用于有限的广告目的。“有限的广告目的”指的是频率上限、归属、转换事件、估计独特用户的数量、广告欺诈检测、仅为广告目的进行调试等,以及苹果公司为广告支持api所允许的广告的其他用途。
如果您还没有这样做,请停止使用UIDevice类的唯一标识符属性提供的唯一设备标识符(UDID)。该属性在iOS 5.0中被弃用,应用程序商店不接受使用该标识符的新应用程序或应用程序更新。相反,应用程序应该在合适的情况下使用UIDevice类的标识符供应商属性或ASIdentifierManager类的广告标识符属性。
如果你的应用支持音频输入,配置你的音频会话只在你真正计划开始录制的地方录制。如果您不打算立即录制,请不要在启动时配置您的音频会话。当应用程序配置他们的音频会议记录时,系统会提醒用户,并允许用户为你的应用程序禁用录制。
表1-2列出了iOS支持的资源和数据授权类型。对于每个项目,该表显示了目的字符串键和用于检查授权状态的API。
重要:当您的应用程序试图使用一个受保护的项目时,系统会提示用户请求允许访问。从ios10开始,你的info.plist文件必须包含一个目的字符串,用于在权限警报中显示每个这样的项。如果您的应用程序试图访问受保护的项,而不提供相应的目的字符串,则应用程序退出。(该行为同样适用于iMessage应用程序,该应用程序必须包括表1-2中列出的相关键,然后才能访问设备的摄像头或麦克风。)
对于一些受保护的数据和资源,iOS框架提供了用于检查和请求授权的专用API,如表1-2所示。
因为用户可以在任何时候通过使用设置更改授权,在访问任何这些项之前检查授权状态。(有些特性,特别是动态和HomeKit,不提供用于检查系统授权状态的专用API。详见表1-2。
表1-2
数据资源 | info.plist中目的字符串key | 系统授权api |
---|---|---|
蓝牙外设 | NSBluetoothPeripheralUsageDescription | 使用CBCentralManager类的state属性检查使用蓝牙外围设备的系统授权状态 |
日历数据 | NSCalendarsUsageDescription | 使用EKEventStore类的方法authorizationStatusForEntityType: 来检查系统授权状态以访问日历数据。 |
相机 | NSCameraUsageDescription | 使用AVCaptureDeviceInput类的方法deviceInputWithDevice:error: 来检查系统授权状态,以便使用设备摄像头。 |
联系人 | NSContactsUsageDescription | 使用CNContactStore类的方法authorizationStatusForEntityType: 来检查系统授权状态以访问联系人数据。 |
Health sharing | NSHealthShareUsageDescription | 使用HKHealthStore类的方法authorizationStatusForType: 来检查系统授权状态以访问健康数据。 要请求授权,请使用requestAuthorizationToShareTypes:readTypes:completion:方法。 |
Health updating | NSHealthUpdateUsageDescription | 使用HKHealthStore类的方法authorizationStatusForType: 来检查系统授权状态以访问健康数据。 要请求授权,请使用requestAuthorizationToShareTypes:readTypes:completion:方法。 |
HomeKit | NSHomeKitUsageDescription | 当应用程序首次尝试访问HMHomeManager类的属性时,系统会向用户提供一个授权请求。 |
Location | NSLocationAlwaysUsageDescription, NSLocationWhenInUseUsageDescription |
使用CLLocationManager类的authorizationStatus方法来检查系统授权状态以访问位置数据。 若要请求授权,请使用requestWhenInUseAuthorization或requestAlwaysAuthorization方法。 |
麦克风 | NSMicrophoneUsageDescription | 使用AVAudioSession类的recordPermission方法检查系统授权状态,以便使用设备麦克风。 要请求授权,请使用requestRecordPermission:方法。 |
Motion | NSMotionUsageDescription | 检查从CMMotionActivityManager类的queryActivityStartingFromDate:toDate:toQueue:withHandler: 方法的CMErrorNotAuthorized错误来检查加速表访问的系统授权状态。 |
音乐和媒体库 | NSAppleMusicUsageDescription | 使用ALAssetsLibrary类的authorizationStatus方法来检查系统授权状态以访问媒体资产。 |
Photos | NSPhotoLibraryUsageDescription | 使用PHPhotoLibrary类的authorizationStatus方法检查系统授权状态,以便访问照片库。 |
Reminders | NSRemindersUsageDescription | 使用EKEventStore类的方法authorizationStatusForEntityType: 来检查系统授权状态以访问提醒数据。 |
Siri | NSSiriUsageDescription | 使用INPreferences类的siriAuthorizationStatus方法检查使用Siri的系统授权状态。 要请求您的应用程序授权使用SiriKit,请使用requestSiriAuthorization:方法。 |
语音识别 | NSSpeechRecognitionUsageDescription | 使用SFSpeechRecognizer类的authorizationStatus 方法检查系统授权状态,以便使用语音识别。 要请求您的应用程序授权使用语音识别,请使用请求授权方法。 |
TV provider | NSVideoSubscriberAccountUsageDescription | 使用VSAccountManager类的checkAccessStatusWithOptions:completionHandler: 方法来检查系统授权状态,以访问用户的视频服务订阅信息。 要请求授权,请使用enqueueResourceAuthorizationRequest:completionHandler:方法。 |
查看表1-2作为你应用程序隐私行为的起点,而不是一个全面的清单。这个表的内容会在iOS更新中出现。
国际化应用程序
因为iOS应用程序在很多国家都有分布,本地化你的应用程序的内容可以帮助你接触到更多的客户。用户在本地化使用本地语言时更有可能使用应用程序。当您将用户面对的内容分解为资源文件时,将该内容本地化为一个相对简单的过程。
在本地化你的内容之前,你必须国际化你的应用程序,以方便本地化过程。国际化应用程序包括将任何面向用户的内容分解为可本地化的资源文件,并为存储该内容提供特定于语言的项目(.lproj)目录。它还意味着在使用特定于语言和特定于语言环境的内容时使用适当的技术(例如日期和数字格式)。
对于一个完全国际化的应用程序,本地化过程将为您创建新的特定于语言的资源文件集,以添加到您的项目中。典型的iOS应用程序需要以下类型的资源文件的本地化版本:
故事板文件(或nib文件)-故事板可以包含文本标签和其他需要本地化的内容。您可能还需要调整接口项的位置,以适应文本长度的更改。(类似地,nib文件可以包含需要本地化的文本或需要更新的布局。)
Strings文件- Strings文件(因此得名,因为它们的. Strings文件扩展名)包含应用程序显示的静态文本的本地化版本。
图像文件-你应该避免本地化图像,除非图像包含特定文化的内容。只要有可能,您应该避免直接在映像文件中存储文本。对于在应用程序中加载和使用的图像,将文本存储在字符串文件中,并在运行时将文本与基于映像的内容组合在一起。
视频和音频文件——您应该避免本地化多媒体文件,除非它们包含特定于语言的或特定于文化的内容。例如,您想要本地化一个包含画外音的视频文件。
有关国际化和本地化过程的信息,请参见国际化和本地化指南。有关在您的应用程序中使用资源文件的正确方法的信息,请参见资源编程指南。