Alternatives to weak linking in iPhone SDK?
You should be weak linking against the new frameworks. Alongside that you should be checking the availability of new APIs using methods like NSClassFromString
, respondsToSelector
, instancesRespondToSelector
etc.
Eg. Weak linking against MessageUI.framework (an old example, but still relevant)
First check if the MFMailComposerController
class exists:
Class mailComposerClass = NSClassFromString(@"MFMailComposerController");
if (mailComposerClass != nil)
{
// class exists, you can use it
}
else
{
// class doesn't exist, work around for older OS
}
If you need to use new constants, types or functions, you can do something like:
if (&UIApplicationWillEnterBackgroundNotification != nil)
{
// go ahead and use it
}
If you need to know if you can use anew methods on an already existing class, you can do:
if ([existingInstance respondsToSelector:@selector(someSelector)])
{
// method exists
}
And so on. Hope this helps.
Does bitcode support weak linking third party frameworks?
In your case, you will need to wait for the fix in framework itself.
We've got similar issue while distributing our framework, which I described here and I just wan't to share results of our investigation, because seems that no-one has published their results.
No needs to distribute without bitcode. Long story short, there were LLVM instrumentation included, which prevents AppStore processing. I've written a whole blog about XCode 12 and BigSur issues with XCFramework.
To sum up, here is a few required steps to make sure while creating XCFramework
for distribution:
- Using archive builds is a MUST, release build isn't enough
BUILD_LIBRARY_FOR_DISTRIBUTION
must be set toYES
SKIP_INSTALL
must be set toNO
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO
to turn off GCC instrumentation and remove them from the binaryCLANG_ENABLE_CODE_COVERAGE = NO
to turn off code coverage tools from the binary
Having all of the above helped to solve our preparing and distribution problem and hopefully save you some time if you happened to face same issues as we did.
Weak Link My Own Objective-C Class
To weak link a class e.g. MyUploadManager
in your own executable:
To keep the linker happy, add this to
Other Linker Flags
in the project:-Wl,-U,_OBJC_CLASS_$_MyUploadManager
This allows the class symbol to be undefined even if it is not built into your executable. It will be considered for dynamic lookup instead, effectively the same as a dynamic library symbol.
To keep the runtime happy, add this to your class header:
__attribute__((weak_import)) @interface MyUploadManager
When the dynamic linker runs, it substitutes a
nil
for the class symbol rather than crashing.
Now you can run this without either linker or runtime errors:
if ([MyUploadManager class]) {
self.uploadButton.hidden = NO;
}
Note: As of Xcode 7, the -U
linker options conflicts with BitCode, so you may not be able to use this technique for future projects.
Weak linking to support previous iOS versions
I think I found the solution (please can someone confirm this?):
You cannot use the simulator to test if your apps run with a previous iOS version. It only works on the device, according to Apple:
iPhone OS Note: Mac OS X v10.6 does not support using iPhone
Simulator SDKs prior to version 3.0.
In addition, when building with the
simulator SDKs, the binary runs only
on the same OS version as the SDK, not
on earlier or later versions.
This seems really dull. How am I supposed to test backwards compatibility without having one physical iPhone for each SDK version? Not good.
How do you optionally use iPhone OS 3.0 features in a 2.0 compatible app?
Apple has an example of how to do this, specifically making a 2.x-compatible app that uses MFMailComposeViewController....
http://developer.apple.com/iphone/library/samplecode/MailComposer/index.html
the answer involves compiling with the 3.0 SDK, setting the deployment target to 2.x, ensuring that the 3.0 frameworks are marked as "weak" references, and then doing the right thing to make your code work if you're on a device where the new frameworks aren't present.
iOS Framework weak link: undefined symbols error
From the description of your issue, I assume you already know how to make Xcode weakly link against the framework by setting it as 'Optional'.
You have two problems to solve: Class availability and symbol availability. Apple covers this in the Framework Programming Guide: Frameworks and Weak Linking and the SDK Compatibility Guide: Using SDK Based Development
Class availability
This is pretty straightforward: use NSClassFromString()
to see if the class is available in the current environment.
if (NSClassFromString("CLLocationManager") != NULL){
If the class is available it can be instantiated and sent messages, otherwise it cannot.
Symbol availability
What you are specifically interested in is using constants or structs from a weakly linked framework. A C-style function would be similar, but those are not a concern when using CoreLocation. We'll use a CoreLocation constant as an example.
Every time you use it you MUST check to make sure it exists:
if (&kCLErrorDomain != NULL){
// Use the constant
}
Note that the &
takes the address of the constant for the comparison.
Also note that you CANNOT do this:
if (kCLErrorDomain){
// Use the constant
}
Or this:
if (&kCLErrorDomain){
// Use the constant
}
Constant symbols can also be lookup up at runtime using dlsym.
Using the negation operator in this way will not work. You must check the address of the constant against the NULL address.
I have put a very simple example of an application that is using a static library which weak links against Core Location on GitHub. The example application does not link against Core Location:
But the dependency does, as an optional (weak) framework:
Related Topics
Swift: Testing Optionals for Nil
Xcode Is Creating Generic Xcode Archive Instead of iOS App Archive
iPhone Uitextfield Background Color
Remove Uisegmentedcontrol Separators Completely. (Iphone)
Complete List of iOS App Permissions
Using Custom Fonts in Interface Builder
iOS Provisioning and Certifcates - Will Revoke/Renew Effect App Store Apps
Adding Glow Effect to Uibutton - iOS
How to Use Swift Repl with iOS Sdk
How to Cache Videos? iOS - Swift
How to Set an Title of the Currently Playing Audio in iPhone Lock Screen
iOS 4.3 Hide Status Bar Permanently
Xcode Crash Organizer Does Not Symbolicate .Xccrashpoint Files
How to Apply Filter to Video Real-Time Using Swift
Check If App Is Ad-Hoc|Dev|App-Store Build at Run Time
Tableview Reloaddata VS. Beginupdates & Endupdates
Request Permissions Again After User Denies Location Services