重要的提示:
这个答案是在 iOS 8 发布之前写的。虽然技术细节仍然适用于系统框架,但现在可以构建您自己的动态链接框架并在您的应用程序包中提供。有一些限制,例如,只有应用程序及其扩展可以链接到嵌入式框架的同一实例,但事实仍然是自定义的动态链接框架are自 iOS 8 起可能。如果您想了解更多信息,请参阅本指南 https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html (使用嵌入式框架共享代码)和 WWDC 2014 年第 416 场会议,构建现代框架.
原答案:
没有一个(平台)框架是真正的“包含在捆绑包中“。相反,您的应用程序有一个引用(”link将其添加到“将二进制文件与库链接”构建阶段后,将其添加到框架。框架已预先安装在设备上。当您运行应用程序时,所有应用程序的框架引用都由动态链接器解析(在device),这意味着框架代码已加载,以便您的应用程序可以使用它。
某些框架可能无法在您想要支持的所有设备上使用,例如,PassKit 是在 iOS 6 中引入的。如果您在 iOS 5 设备上运行链接到 PassKit 的应用程序,它会在启动后立即崩溃,因为动态链接器无法找到设备上的框架。但是,如果您弱链接 PassKit,动态链接器会将所有框架的符号设置为nil
,如果找不到框架。这可以防止应用程序崩溃,您可以在运行时检查符号的可用性,例如:
if ([PKPass class]) {
// Class is available - use it
PKPass *pass = [[PKPass alloc] init];
}
[PKPass class]
可以在所有设备/系统上安全使用,因为PKPass
类符号将是nil
在旧系统和消息传递上nil
在 Objective-C 中不是问题。
有关弱链接的更多信息:苹果文档 https://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html
真正回答你的问题:
这是否意味着框架仅在导入到某个地方时才包含在捆绑包中?
No.该框架将始终从应用程序链接。仅当您的应用程序运行的实际设备上找不到该框架时,才不会加载该框架。
一种解决方案是为调试和应用商店构建设置单独的目标。另一种方法是不使用 Xcode 中内置的“将二进制文件与库链接”构建阶段,而是通过链接器选项链接调试框架。可以为每个配置(调试/发布/...)单独指定这些,如下所示:
如果您想对其进行弱链接,请使用-weak_framework PassKit
(当然,PassKit 只是这里的一个示例...插入您的框架的名称)。如果您的调试框架不在默认框架目录之一中,您可能必须提供完整路径或修改框架搜索路径。另外,您可能应该使用宏来确保使用调试框架的代码不会进入 App Store 构建。
Edit:自 Xcode 5 以来的另一个选择是使用@import <FrameworkName>;
。这样,您可以将“链接二进制...”阶段留空并触发代码中框架的链接。然后您可以使用宏,例如DEBUG
确保某些框架不用于 App Store 构建。有一个很好的答案 https://stackoverflow.com/questions/18947516/import-vs-import-ios-7关于@import
.