这对于“弱连结”意味着什么?一个框架? [英] What does it mean to "weak-link" a framework?

查看:108
本文介绍了这对于“弱连结”意味着什么?一个框架?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Xcode中,我可以将框架设置为可选而不是必需,这意味着框架是弱链接。

意味着框架仅在导入某处时才被包含在捆绑包中



我想弱连接一些使用私有API ,并且我不希望它们出现在App Store构建中。 解决方案

重要说明
这个答案是在iOS 8发布之前编写的。虽然技术细节仍然适用于系统框架,但现在可以构建自己的,动态链接的框架,这些框架在您的应用程序包中提供。有限制,例如,只有一个应用程序及其扩展可以链接到嵌入式框架的同一个实例,但事实是自定义动态链接框架自iOS 8以来可能是可能的。如果您想要了解更多信息,请参阅本指南使用嵌入式框架共享代码)和WWDC 2014会话416,构建现代框架

原始答案
(平台)框架中没有一个确实是包含在该包中的。相反,一旦将您的应用程序添加到Link Binary with Library构建阶段,您的应用程序就会对该框架提供参考( link )。这些框架预先安装在设备上。运行应用程序时,所有应用程序的框架引用都由动态链接器(在设备上)解析,这意味着框架代码已加载,因此您的应用程序可以使用它。



有些框架可能无法在您打算支持的所有设备上使用,例如,PassKit是在iOS 6中引入的。如果您运行的应用与iOS 5设备上的PassKit链接,则它会在启动后立即崩溃,因为动态链接器无法在设备上找到框架。但是,如果您将PassKit连接得很弱,那么如果找不到框架,动态链接器将把所有框架的符号设置为 nil 。这可以防止应用程序崩溃,您可以在运行时检查符号的可用性,例如:

  if([PKPass class] ){
// Class is available - use it
PKPass * pass = [[PKPass alloc] init];

$ / code>

[PKPass class] 在所有设备/系统上都可以安全使用,因为旧版系统上的 PKPass 类符号将为 nil nil 在Objective-C中不是问题。

更多关于弱链接: Apple文档



要真正回答你的问题:


这是否意味着框架只在包中才会被包含?


否。该框架将始终从应用中链接。只有在应用程序运行的实际设备上找不到框架时,才会加载框架。



一个解决方案是为Debug分开目标和App Store构建。另一种方法是不使用Xcode内置的Link Binary with Library构建阶段,而是通过链接器选项链接调试框架。这些可以分别为每个配置(Debug / Release / ...)指定,例如: .com / S68KS.pngalt =通过链接器标志添加框架>



如果您想弱链接它,请使用 -weak_framework PassKit (当然,PassKit只是一个例子,插入框架的名称)。如果您的调试框架不在默认框架目录之一中,则可能需要提供完整路径或修改框架搜索路径。另外,您应该使用宏来确保使用调试框架的代码不会使其进入App Store构建。



编辑

strong>:自Xcode 5以来,另一种选择是使用 @import< FrameworkName> ;; 。这样,您可以将链接二进制...阶段留空,并触发代码中框架的链接。然后可以使用诸如 DEBUG 之类的宏来确保某些框架不用于App Store构建。有关 @import 出色答案 c>。


In Xcode, I can set a framework to "Optional" instead of "Required", which then means the framework is weak linked.

Does that mean the framework is only included in the bundle when it is imported somewhere?

I want to weak-link a few debugging frameworks which use private API, and I do not want them to appear in the App Store build.

解决方案

Important note: This answer was written before iOS 8 was announced. While the technical details still apply to system frameworks, it is now possible to build your own, dynamically linked frameworks that ship within your app bundle. There are restrictions, e.g., only an app and its extensions can link to the same instance of an embedded framework, but the fact remains that custom, dynamically linked framework are possible since iOS 8. If you want to learn more, refer to this guide (Using an Embedded Framework to Share Code) and WWDC 2014 session 416, Building Modern Frameworks.

Original Answer: None of the (platform) frameworks is really "included in the bundle". Instead, your app has a reference ("link") to a framework once you add it to the "Link Binary with Library" build phase. The frameworks are pre-installed on the devices. When you run an app, all the app's framework references are resolved by the dynamic linker (on the device), which means the framework code is loaded so your app can use it.

Some frameworks may not be available on all the devices you intend to support, e.g., PassKit was introduced in iOS 6. If you run an app that links against PassKit on an iOS 5 device, it crashes right after launch, because the dynamic linker cannot find the framework on the device. However, if you weak-link PassKit, the dynamic linker will set all the framework's symbols to nil, if the framework could not be found. This prevents the app from crashing and you can check for the symbols' availability at runtime, e.g.:

if ([PKPass class]) {
  // Class is available - use it
  PKPass *pass = [[PKPass alloc] init];
}

[PKPass class] is safe to use on all devices/systems since the PKPass class symbol will be nil on older systems, and messaging nil is not a problem in Objective-C.

More on Weak-Linking: Apple Documentation

To really answer your question:

Does that mean the framework is only included in the bundle when it is imported somewhere?

No. The framework will always be linked from the app. Only when the framework is not found on the actual device your app is running on, then the framework will not be loaded.

One solution would be to have separate targets for Debug and App Store Builds. An alternative is to not use the built-in "Link Binary with Library" build phase from Xcode, but to link the Debug frameworks via linker options. These can be specified for each configuration (Debug/Release/...) separately, like so:

If you'd want to weak-link it, use -weak_framework PassKit (PassKit, of course, being just an example here... insert the name of your framework) instead. If your Debug framework is not in one of the default framework directories, you might have to provide a full path or modify the Frameworks Search Path. Plus, you should probably use macros to make sure none of the code using the debug framework(s) makes it to the App Store build.

Edit: Another option since Xcode 5 is to use @import <FrameworkName>;. This way, you can leave your "Link Binary..." phase empty and trigger the linking of frameworks in code. You can then use macros such as DEBUG to make sure some frameworks aren't used for App Store builds. There's an excellent answer regarding @import.

这篇关于这对于“弱连结”意味着什么?一个框架?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆