Framework 编程指南文档笔记 (下)创建framework指南,FrameWork Progremming Guide
创建framework指南
API命名指南
全局命名空间中的元素(例如类,函数和全局变量)应该都具有唯一的名称。 虽然两级命名空间可帮助dynamic linker在运行时找到正确的符号,但该功能不会防止由于多重定义的符号而出现静态链接错误。 例如,假设两个不同的Framework 定义了一个具有相同名称的符号。 如果你要创建一个包含这两个Framework 的项目,那么如果引用了相关符号,则会遇到静态链接错误。 静态链接器负责选择使用哪个Framework ,然后生成dynamic linker所需的两级命名空间提示。 因为两个Framework 都定义了符号,所以静态链接器不能选择并生成错误。
你应该尝试那些明确地选择将每个符号与你的Framework 有关联的那种名称。 例如,考虑为所有外部符号名称添加一个短前缀。 前缀有助于区分Framework 中的符号与其他Framework 和库中的符号。 他们还向其他开发人员清楚了解正在使用哪种Framework 。 典型的前缀包括第一对字母或你的Framework 名称的首字母缩略词。 例如,Core GraphicsFramework 中的函数使用前缀“CG”。
如果你正在编写Objective-C类的类别,则还应在方法名称中使用某种唯一的前缀。 因为可以从多个来源动态加载类别,所以唯一的前缀有助于确保类别中的方法与其他类别中的方法不冲突。
Framework 的性能影响
在你创建自定义Framework 之前,应该仔细考虑其预期用途。 在运行时加载和使用Framework 有一定的开销。 虽然这种开销不高,特别是如果你的Framework 和应用程序是预先绑定的。
Framework 在代码被多个应用程序共享时最为有效。 如果你正在设计一套应用程序,你可以创建一个定制Framework 来存储套件中所有应用程序访问的通用代码。 同样,你可能希望在内部创建一个私有Framework 以从通用的,可重用的代码中分离出特定于应用程序的代码。 虽然你可以在创建的每个应用程序中嵌入此Framework ,但可以简化对可重用代码的维护。
包含在你的Framework 中的内容
Framework 为多个应用程序提供共享资源。 如果你正在定义一个定制Framework ,你应该牢记这个target。 尽可能多的,你的Framework 不应该包含与特定应用程序绑定的代码。 相反,它应该包含可重复使用或多个应用程序共有的代码。
除了代码之外,你还可以在Framework 中包含其他类型的资源。 在Framework 的Resources目录中,可以包含可能在应用程序中找到的nib文件,图像,声音文件,本地化文本以及任何其他类型的资源。 在运行时,应用程序使用它们用于其应用程序特定资源的相同捆绑机制加载你的Framework 资源。
在Framework 代码中使用C ++
从动态共享库中导出C ++类接口存在固有的问题。 这些问题是由于缺乏标准化的调用约定而导致C ++语言与C语言不同的扩展。
为了消除使用不同编译器构建的库之间的链接问题,编译器供应商同意支持C语言的标准化调用约定。 这些标准要求供应商以一致的方式生成C代码,以保证一个库中的代码可以调用另一个库中的代码。 虽然已经为C++语言扩展提出了这样的标准,但它尚未最终确定。 因此,不能保证两个不同的C ++库之间的调用是可行的。
如果你打算在Framework 中使用C ++代码,避免不兼容问题的最佳方法是使用ANSI C函数为你的C ++类封装接口。 通过将C ++用于你的实现,并将ANSI C用于你的界面,你可以继续使用你的首选语言进行开发,同时为客户端提供兼容的界面以供调用。
如果你需要从你的Framework 中导出类接口,Apple建议你使用Objective-C而不是C ++来定义类。 Objective-C语言确实有一套标准化的调用约定,使你能够从你的Framework 中公开类接口。
有关在共享库中使用C ++的更多信息和指导,请参阅“ C ++运行时环境编程指南” 。
不要创建 Umbrella Framework
尽管可以使用Xcode创建Umbrella Framework,但对于大多数开发人员来说,这样做是不必要的,因此不推荐使用。 苹果使用Umbrella Framework来掩盖操作系统中的库之间的一些相互依赖关系。 在几乎所有情况下,你都应该能够将代码包含在单个标准framework bundle中。 另外,如果你的代码是足够模块化的,你可以创建多个Framework ,但在这种情况下,模块之间的依赖关系是最小的或不存在的,并且不应该为它们创建一个伞型结构。
安装Framework的位置
OS X在系统上的多个固定位置查找公共Framework 。 如果你正在为其他开发者创建一个Framework ,你应该把它放在其中一个位置。 如果你正在创建一个私有Framework ,你可以将它嵌入到应用程序中,或者把它放在一个自定义位置。 无论哪种情况,你都必须做一些额外的工作来加载你的Framework 代码和资源。
创建一个Framework
使用Xcod为你的代码创建一个Framework 。 随着你向Framework 添加major version,你还需要能够维护你的项目。 以下部分向你展示如何执行这两项任务。
创建你的Framework
配置你的Framework 项目
当你创建一个新的Framework 时,你可能需要修改几个配置选项。 这些选项使你可以更轻松地将你的Framework 分发给客户,并在未来开发周期后保证其兼容性。 下表出了你应该为Framework 设置的一些选项。
选项
|
描述
|
Framework identifierFramework 标识符
|
一种Java风格的软件包标识符,用于唯一标识系统的Framework 。 你应该始终设置此选项。
|
Framework versionFramework 版本
|
目前主要的Framework 版本。
|
Current version当前版本
|
目前的Framework 版本。
|
Compatibility version兼容版本
|
该Framework 的最新版本包括对公共接口的更改。
|
Exported symbols导出的符号
|
你想要导出到其他程序的Framework 符号列表。
|
Installation path安装路径
|
最终将安装Framework 的目录名称。
|
Preferred address首选地址
|
对于在OS X v10.3.9及更早版本中部署的Framework ,指定用于预绑定操作的首选内存地址。 在10.4和更高版本中部署Framework 时,不需要此值。
|
测试你的Framework
当你构建一个Framework 时,默认情况下,Xcode会将它放置在项目目录的build子目录中。 虽然你可以告诉Xcode将你的Framework 安装到最终部署位置,但在开发过程中你可能希望将它留在原来的位置。 如果你这样做,你可能需要告诉测试应用程序在哪里找到你的Framework 。
如果你的Framework 项目包含测试应用程序的其他target,则Xcode将这些应用程序与你的Framework 构建在相同的文件夹中。 与你的Framework 一起构建的测试应用程序会自动找到该Framework 。 但是,如果将测试应用程序构建到不同的构建目录中,除非你告诉他们在哪里找到它,否则这些应用程序可能无法找到你的Framework 。
应用程序寻找Framework 的常用方法是查看标准位置。 但是,你可能不想在每次更改Framework 时重新安装Framework 。 在这种情况下,你可以使用DYLD_FRAMEWORK_PATH环境变量准确地告诉测试应用程序在哪里找到Framework 。 将这个变量添加到可执行文件告诉dyld在哪里寻找额外的Framework ,如果它没有在标准位置找到它需要的。 以下步骤说明如何在Xcode中设置此变量。
- Open your application project in Xcode.
- In the Groups & Files pane, open the Executables group, select the executable to configure, open its Info window, and click Arguments.
- Add an entry to the environment variables list.
- Set the name of the environment variable to DYLD_FRAMEWORK_PATH.
- Set the value of the variable to the full pathname of the directory containing your framework.
To specify multiple framework directories, separate the pathnames with a colon. For example, you could have a value such as the following value on this line: /Users/lynn/MyFrameworks:/Volumes/Keylime/MyOtherFrameworks.
在应用程序bundle中嵌入私有Framework
如果你需要使用应用程序分发私有Framework ,首选的解决方案是将Framework 嵌入你的应用程序包中。 嵌入Framework 将Framework 与应用程序不可分割地联系起来,并确保应用程序始终具有正确的操作所需的Framework 版本。 嵌入Framework 也使其他开发人员清楚,他们不应该链接到该Framework 。
注意:如果多个应用程序必须共享一个私有Framework ,则应该将该Framework 安装在系统上的一个可用PrivateFrameworks目录中,而不是将其嵌入到一个(或全部)应用程序中。 共享一个Framework 可以更有效地重用Framework 的动态库。
要在应用程序中嵌入Framework ,你必须执行以下几个步骤:
- 你必须配置应用程序target的build phases,以将Framework 置于正确的位置。
- 你必须配置Framework target的安装目录,该目录会告诉Framework 它将在哪里存在。
- 你必须配置应用程序target,以便它在其安装目录中引用Framework 。
可以使用单个Xcode Project或多个项目在应用程序中构建和嵌入Framework 。 使用单个Xcode Project要容易一些,因为它需要较少的配置才能构建Framework 和应用程序。 但是,对于多项目设置,一旦两个项目配置为正确构建,嵌入Framework 的配置步骤基本上与单个Xcode Project相同。
为两个target使用单独的Xcode Project
对应用程序和Framework target使用单个Xcode Project简化了所需的设置。 一旦你创建了你的项目,你只需向它添加两个target:一个用于你的应用程序,另一个用于你的Framework 。 (因为两个target都驻留在同一个项目中,所以在构建时从任一target中查找源文件都没有问题。)之后,只需使用正确的嵌入运行时信息来配置Framework 和应用程序target即可。
你的Framework target的配置涉及告诉它将在哪里安装。 该Framework 需要这些信息,以便它可以找到所需的资源。 由于Framework 通常安装在固定位置,因此通常需要指定相应Framework 目录的完整路径。 然而,当你在一个bundle中嵌入一个Framework 时,Framework 的位置是不固定的,所以你必须使用@executable_path占位符来让Framework 知道它的位置是相对于当前的可执行文件。
- Open an inspector for your framework target and select the Build tab.
- Set the value of the Installation Directory build setting to @executable_path/../Frameworks.
在构建时,Xcode构建你的Framework 并将结果放入构建目录中。 但是,在应用程序可以使用Framework 之前,你必须按如下方式配置应用程序target:
- 你需要将Framework 复制到应用程序的bundle中。
- 你需要将应用程序与Framework 链接起来。
- 你需要在Framework 和应用程序之间创建构建依赖关系。
以下步骤向你展示如何配置你的应用程序target。
- In the Group & Files pane, open your application target to view its current build phases.
- Drag your framework product (located in the Products folder) to the existing Link Binary With Libraries build phase of your application target. This causes the application to link against your framework.
- Add a new Copy Files Build Phase to the application target. (This phase will be used to install the framework in the application bundle.)
- Select the new build phase and open an inspector window.
- In the General tab of the inspector window, set the destination for the build phase to “Frameworks”.
- Drag your framework product to the new build phase.
- Select the application target again and open the inspector window.
- In the General tab of the inspector window, add your framework as a dependency for the application. Adding this dependency causes Xcode to build the framework target before building the application target.
你在应用程序target中建立的构建依赖性会导致在构建应用程序之前构建Framework 。 这非常重要,因为它可以确保你的Framework 的内置版本可用于链接并嵌入到应用程序中。 由于这种依赖性,你可以将Xcode Project的活动target设置为你的应用程序,并将其保留在那里。 构建应用程序现在构建Framework 并将其复制到应用程序包目录中,从而在两者之间建立必要的联系。
为每个target使用单独的Xcode Project
如果你的Framework 和应用程序已经有单独的Xcode Project,那么你可以利用Xcode的跨项目引用将Framework 嵌入到你的应用程序中。 跨项目引用是创建两个单独Xcode Project之间关系的便捷方式。 要在你的应用程序和Framework 之间建立跨项目引用,你需要执行以下操作:
- In your application project, choose Project > Add to Project and select your framework’s .xcodeproj file. Xcode adds the framework project and displays its products in the Groups & Files pane of your application project.
- Modify the Build Products Path setting for both the application and framework targets so that they use the same build directory. You need to modify each target in their original Xcode project file.
- In your application project, modify the Header Search Paths setting of the application target by adding the directories containing any framework header files.
配置好Xcode Project以正确构建之后,可以继续执行将Framework 嵌入到应用程序中所需的配置步骤。 你的Framework 的安装目录必须配置为相对于应用程序的可执行路径。 同样,应用程序target必须将Framework 复制到其包中,并设置必要的链接和依赖关系。 唯一的区别是你必须在自己的Xcode Project中配 置每个target。
构建一个framework的多个版本
在发布Framework 之后,你应该考虑如何管理你的Xcode Project以便将来发布。 更新现有Framework 时,所做更改的类型决定了继续处理项目文件的最佳方式。 例如,主要更改可能需要复制项目文件和维护单独的项目,每个major version都有一个。 另一方面,可以将小的更改加入到现有的Xcode Project中。
更新minor版本
如果你对Framework 进行了细微的更改,则不需要为Framework 创建新的Xcode Project。 但是,你应该始终更新与你的Framework 相关的“当前版本”和“兼容版本”值。 这些值使dynamic linker可以确定是否可以将程序链接到Framework 。
更新major版本
更新major versionFramework 的过程比次要版本的过程更加复杂。 推荐的创建新major version的方法是制作整个Xcode Project文件夹的重复版本,并从此继续开发。 旧的项目文件应该被归档并用于执行遗留版本。 但是,新项目应继续开发。
一旦你有了一个新的项目文件夹,你需要对Xcode Project进行一些修改,以将项target识为major version。 选择你的Framework target并打开检查器窗口。 在“生成”窗格中,修改以下生成选项:
- Increment the value of the Framework Version build setting to the next sequential value.
- Increment the value of the Current Library Version build setting.
- Update the value of the Compatibility Version build setting to match the updated Current Library Version.
- Update any build settings whose path information includes the framework major version designator. For example, if you have a Copy Files build phase based on the product directory, you may need to update that path. Or make sure the paths are specified using the framework’s Current symbolic link.
- In the Properties pane of the framework target Info window, update the version number that gets stored in your framework’s information property list.
一旦对代码进行了更改,就可以构建Framework target。 你得到的是一个新的framework bundle,只包含新的major version。
在安装过程中,如果你的Framework 版本尚不存在于target系统上,请让安装程序按原样复制你的Framework 套件。 但是,如果存在该Framework 的现有版本,请让安装程序将新Framework 目录的内容复制到旧目录中。 你的安装程序脚本必须将旧Framework 捆绑中的符号链接替换为指向新版本Framework 的符号链接。 但是,复制新的主版本应该保留任何旧版本。 这允许现有应用程序继续运行,而新版本使用更新后的Framework 。
警告:不要尝试通过现有的framework bundle构建新版本的Framework 。 执行项目的全新构建会删除该包的全部内容,包括任何旧版本。 在安装过程中维护单独的项目并复制文件更安全。
你可能还希望安装程序删除过时版本的Framework 的任何头文件或文档。 此步骤是可选的,由你自行决定。 但是,建议在开发过程中防止开发人员意外地包含过时的一组头文件或查看较早的文档。
在运行时初始化一个Framework
当一个Framework 首次被一个独特的进程加载时,系统调用Framework 的初始化代码。 在OS X v10.4之前,Framework 初始化通常由Framework 第一次加载时调用的单个例程组成; 但是,在OS X v10.4及更高版本中,使用模块初始化程序和终结器成为首选技术。 模块的 Initializers 的主要优点是可以在dynamic linker有机会加载模块的 Initializers 依赖的其他库之后调用它们。 Framework 初始化例程也是如此,这些例程在加载时立即调用,并可能在其他重要模块(如C ++运行时)加载之前加载.
初始化例程和性能
由于所有类型的初始化例程都是在 framework 加载时调用的,因此通常在应用程序启动时调用它们。 启动时间通常是执行大量工作的时间,因为它可能导致相应的应用程序感觉迟缓。 在编写初始化例程时,尽可能少做一些工作,以使你的 framework 处于可控状态。 例如,不要立即分配 framework 数据结构,而应考虑在需要时lazy initialize数据结构。 另外,请避免执行任何可能导致延迟的操作,例如访问网络。
请记住,如果你的 framework 包含静态数据,则该数据也必须在加载时进行初始化。 尽量减少你的 framework 使用的静态变量的数量也可以帮助减少初始化性能。
定义模块的 Initializers和 Finalizers
模块的 Initializers 是初始化 framework 的首选方式。 模块初始化程序是一个静态函数,它不接受任何参数并且不返回任何值。 它是使用构造函数编译器属性声明的,如下图所示。与任何静态初始化函数一样,你应该通过在初始化代码周围放置一个守护变量来防止函数被两次调用。
framework 可以定义多个模块初始化函数。dynamic link editor在初始化所有静态变量后、在调用 framework 中的任何其他函数或方法前,调用所有模块初始化函数。如果模块初始化函数中的代码依赖于其他库(例如C ++ runtime),则dynamic linker在调用函数之前加载这些库。当 framework 由进程加载时,每个模块初始化函数仅被调用一次。模块的 Initializers 按照编译器遇到的顺序执行。
任何模块初始化函数的符号都不能由 framework 导出。默认情况下,Xcode导出项目头文件中声明的所有符号。你可以通过显式导出符号列表或通过隐藏特定符号(以及导出其他所有符号)来限制导出的符号集。有关如何配置 framework 导出的信息,请参Exporting Your Framework Interface。
在OS X v10.4及更高版本中,模块初始化程序可以访问当前进程的启动参数,如下图所示。 framework 可能使用这些参数来获取有关应用程序启动配置的信息,例如任何环境变量或在launch line上传入的flags。
__attribute__((constructor))
|
static void initializer(int argc, char** argv, char** envp)
|
{
|
// Initialization code.
|
}
|
使用 初始化例程
如果你的 framework 必须在10.4之前的OS X版本中运行,你仍然可以根据需要使用 framework 初始化函数来初始化 framework 数据结构。 然而,在实施初始化程序时,尽可能少做一些工作很重要。 因为你的初始化例程在加载时立即运行,所以其他代码模块可能无法加载并可供使用,因此重要的是不要执行涉及其他库的任何复杂初始化。
初始化函数的签名与标准模块初始化程序的签名相同:
void MyFrameworkInit()
|
要加载例程,必须使用INIT_ROUTINE标志将例程的名称传递给链接器。在命令行中,你可以使用-init选项设置此标志,然后是你的初始化例程的名称。在Xcode中,通过执行以下操作来设置此标志:
- Select your framework target and open an inspector window.
- In the Build pane, find the Initialization Routine build setting. It is with the Linking options.
- Set the value of this setting to the symbol name of your initialization routine.
对于基于ANSI C的例程,符号名称只是带有前导下划线字符的函数名称。例如,MyFrameworkInit函数的符号名称是_MyFrameworkInit。你不应该使用C ++例程来初始化函数。
如果你在构建具有指定初始化例程的 framework 时遇到问题,可以尝试解决该问题。使用nm命令行工具确认例程的符号名称。你也可以使用nm和-g选项来确保你的例程的全局符号被库导出。如果不是,请检查是否有导出文件,并确保你的例程包含在其中。
重要提示:在OS X v10.3.9及更高版本中,不使用 framework 初始化函数中的C ++代码尤为重要。 在10.3.9之前,C ++运行时被打包为静态库并链接到应用程序可执行文件中。 在OS X v10.3.9及更高版本中,库被打包为动态共享库,并且只在需要时加载,这可能是在加载 framework 之后。 尝试使用C ++功能的 framework 初始化函数可能随后失败或导致应用程序终止。
导出你的Framework 接口
当你使用Xcode构建Framework 或者 App时,linker 默认在你代码里到处所有的符号。对于一个交付的有多个符号的framework,这个操作会在运行时带来性能问题。当一个framework加载了,dynamic lind editor 加载和framework关联的符号文件。如果一个framework包含许多私有方法,那么这些私有方法的符号文件不会被使用,但是会和公开方法一起被加载。加载这些额外符号不仅费内存,也需要更多符号列表查找工作。
Xcode 中,你可以通过在linker options里指定导出文件来到处特定的符号。
创建你的导出文件
一个导出文件时一个简单的文本文件,包含你要导出的符号列表。通过在Xcode中添加空文件来创建它。给这个文件添加你想导出的符号列表,每个符号一行。
对于ANSI C-based 代码,通常只需在函数或变量的名称前加一个下划线字符即可得到符号名称。 对于像C ++这样使用破坏符号名称的语言,你可能需要运行nm工具来获取现有符号名称的列表。 使用-g选项运行nm以查看当前导出的符号。 然后,你可以复制该工具的输出并将其粘贴到导出文件中,从而删除任何无关信息。 以下文本显示了由nm生成的Cocoa framework 的一些示例输出:
要在这个输出里导出指定的framework方法,需要创建一个text文件,如下:
_InitCocoaFW
|
_addNumbers
|
_getInitDate
|
你可以注释移除一个符号,如下:
_InitCocoaFW
|
_addNumbers
|
#_getInitDate
|
指定你的导出文件
通过Xcode导出:
- Open your project in Xcode.
- Add your exports file to the project, and place it in the Resources group.
- Open the framework target’s Info window and click Build.
- Set the Exported Symbols File build setting to the name of your exports file.
You can locate this build setting by choosing All from the Collections pop-up menu and entering its name in the search field.
如果要导出除限制子集以外的所有符号,则可以使用“Unexported Symbol Files”build设置来执行此操作。像以前一样创建你的符号文件,但这次包括你不想导出的符号列表。在目标的链接构建设置中,找到“未导出符号文件”设置并将其值设置为文件的名称。如果Unexported Symbol Files构建设置不存在,因为它可能不在V2.2之前的Xcode版本上,你可以使用“其他链接器标记”构建设置。要隐藏一组符号,请将该构建设置的值设置为以下文本,将exports_filename替换为你的exports文件的名称:-unexported_symbols_list exports_filename
安装你的framework
一旦你准备好了framework,你需要觉得在哪里安装。安装位置也帮你决定如何安装framework。
Public Frameworks 的位置
第三方framework能放入许多不同文件系统的位置,基于以下事实:
- 大部分public framework 应该被安装到本地层级 /Library/Frameworks
- 如果你的framework只应该由一个用户使用,你可以在当前用户的 ~/Library/Frameworks 目录,但是,这个操作不好,应该避免。
- 如果framework在跨越本地网络中使用,可以安装到/Network/Library/Frameworks,这个操作也应该避免。
对于几乎所有的情况,在 /Library/Frameworks 中安装 framework 是最佳选择。编译时编译器会自动发现此位置中的 framework ,并在运行时自动发现此动态链接器。链接到其他目录(如~/Library/ Frameworks或/Network/Library/Frameworks)中的 framework 的应用程序必须在构建时指定 framework 的确切路径,以便动态链接程序可以找到它。如果路径更改(如可能用于用户主目录),则动态链接程序可能无法找到该 framework 。
避免在~/Library/Frameworks或/Network/Library/Frameworks中安装 framework 的另一个原因是潜在的性能损失。安装在网络目录或基于网络的用户主目录中的 framework 会导致编译时间显着延迟。通过网络加载 framework 也会减慢目标应用程序的启动速度。
第三方 framework 不应该安装在/System/Library/Frameworks目录中。对这个目录的访问是受限制的,仅限于Apple提供的 framework 。
当你构建应用程序或其他可执行文件时,编译器会在/System/Library/Frameworks中查找 framework 以及指定给编译器的任何其他位置。编译器为可执行文件本身中的任何必需 framework 编写路径信息,以及每个 framework 的版本信息。运行应用程序时,动态链接编辑器会尝试使用可执行文件中的路径找到每个 framework 的合适版本。如果它无法在指定位置找到合适的 framework (可能是因为它已被移动或删除),它会按以下顺序在以下位置查找 framework :
- 连接时的framework的显示路径
- /Library/Frameworks directory.
- /System/Library/Frameworks directory
如果 dynamic linke editor 不能定位需要的framework,会生成一个link edit error,终止程序。
Private Frameworks的位置
用于内部使用的自定义 framework 应安装在使用它们的应用程序内部。 嵌入在应用程序中的 framework 存储在应用程序bundle的Frameworks目录中。 以这种方式嵌入 framework 的优点是它可以确保应用程序始终拥有正确的运行 framework 版本。
嵌入 framework 的限制是你不能在一套应用程序中共享 framework 。 如果你的公司开发一套依赖于相同 framework 的应用程序,则可能需要安装该 framework 的所有应用程序可共享的一个副本。 在这种情况下,你应该将 framework 安装在/Library/Frameworks目录中,并确保 framework 包不包含任何公共头信息。
安装Frameworks
你如何安装 framework 取决于你的 framework 。如果你的 framework 捆绑在一个特定的应用程序中,那么你就不需要做任何特殊的事情。用户可以将应用程序包拖动到本地系统并使用该应用程序,而无需额外的安装步骤。
如果你的 framework 在应用程序外部,你应该使用安装包来确保将其放置在适当的位置。如果你的 framework 的旧版本可能就位,你还应该使用安装包。在这种情况下,你可能需要编写一些脚本来更新现有的 framework 捆绑包,而不是完全替换它。例如,你可能希望安装新的主要版本的 framework ,而不会打扰任何其他版本。同样,如果你有多个依赖于相同 framework 的应用程序,则安装包应该检查 framework 的存在并仅在需要时安装它。
有关创建安装包的更多信息,请参阅Distributing Apps Outside the Mac App Store。
包含 Framework
在Xcode中加入Framework。
注意:如果你不用Xcode构建项目,你必须使用 GCC和LD的-framework选项来指定framework。
使用 #include 直接包含 framework的header文件。如果你用OC,可能需要使用#import。这俩关键字结果一样,但是#import关键字保证header文件只被引用一次。当包含header文件的时候,传统方法时仅包含framework的master header file。master header file 是一个header文件,他的名字和framework名字同名。
对于大部分framework,你可以引用指定的header file,不局限于master header file。但是,当你引用一个umbrella framework时,必须引用 master header file。umbrella framework不允许引用subframeworks里的header file。
非标准目录中定位framework
如果你项目连接的framework不包含在任意标准位置,你必须在Xcode能定位headerfile前,显示指定framework的位置。在 build setting的 Framework Search Path中设置。Xcode传递选项给编译器和linker。
Headers 和 性能
如果你担心包含一个master header file 可能导致程序的性能问题。那么无需担心,OS X接口就是用 framework实现的,接口的代码放在一个 动态共享库里,不再你的可执行代码中。另外,只有你程序使用的code会在运行时载入内存,所以你内存占用也很小。
至于在编译期间包含大量头文件,这可能会导致性能问题。 Xcode提供了一个预编译头文件来加快编译时间。 通过一次编译所有的 framework 头文件,除非添加新的 framework ,否则不需要重新编译头文件。 与此同时,你可以使用包含 framework 中的任何接口,而不会影响性能。
Subframework Linking 的限制
OS X包含两种机制,用于确保开发人员仅与umbrella framework相链接。 一种机制是阻止你选择Subframeworks的Xcode功能。 另一种机制是当你尝试包含Subframeworks头文件时发生的编译时错误。
在Xcode中,添加 framework 命令显示/System/Library/Frameworks中的可用 framework 。
如果你尝试包含Subframeworks中的头文件,则Xcode会生成编译时错误消息。 umbrella framework头文件和Subframeworks头文件包含预处理变量和检查以防止包含Subframeworks头文件。 如果使用不正确的#include语句编译项目,编译器会生成一条错误消息。
END