Onato
Onato

Reputation: 10221

Weak Link My Own Objective-C Class

Is it possible to weak link my own objective-c classes?

I have seen that I can weak link a function or a variable…

extern int MyFunction() __attribute__((weak_import));
extern int MyVariable __attribute__((weak_import));

I would like to have something like this…

if ([MyUploadManager class]) {
  self.uploadButton.hidden = NO;
}

… and be able to compile even if UploadManager.m is not included in the project.

Upvotes: 8

Views: 2317

Answers (3)

Glen Low
Glen Low

Reputation: 4497

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.

Upvotes: 9

Onato
Onato

Reputation: 10221

To weak link a class it can be included in a framework. The compiler can be told to weak link all symbols in a framework using the Other Linker Flag build setting.

-weak_framework <framework_name>

This enables MyModule.framework to weak link against Uploader.framework whilst it is being built. If someone using MyModule.framework does not links against Uploader.framework then, in the example above, the button will not be displayed.

Frameworks and Weak Linking

Upvotes: 1

mipadi
mipadi

Reputation: 410762

You can use the NSClassFromString function:

Class MyUploadManager = NSClassFromString(@"MyUploadManager");
if (MyUploadManager) {
    self.uploadButton.hidden = NO;
}

NSClassFromString returns nil if the class cannot be found.

Upvotes: 4

Related Questions