Alternatives to Weak Linking in iPhone Sdk

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 to YES
  • SKIP_INSTALL must be set to NO
  • GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO to turn off GCC instrumentation and remove them from the binary
  • CLANG_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:

  1. 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.

  2. 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:

TestApp

But the dependency does, as an optional (weak) framework:

optional framework



Related Topics



Leave a reply



Submit