What does it mean to “weak-link” a framework?

青春壹個敷衍的年華 提交于 2019-11-26 20:01:30

问题


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.


回答1:


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.




回答2:


I encountered weak linking when I was using iAds. The problem was if I strong link iAds framework and run the app on a device with SDK which did not supported iAds then it will simply crash. Weak linking allowed to avoid the crashes. I still believe that even with weak linking you still have to check in code if the framework is available or not.




回答3:


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

This depends on how you configured your schemes or targets.

You could use one scheme only for debugging and include your optional framework only there. Use another scheme without the optional framework for release.

UPDATE

To do this, base your new scheme on a project configuration and set OTHER_LDFLAGS as described in hagi's answer.



来源:https://stackoverflow.com/questions/16922013/what-does-it-mean-to-weak-link-a-framework

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!