-
Notifications
You must be signed in to change notification settings - Fork 35
Description
%c() has shortcomings — for instance the compiler has no idea what type it actually is and can’t do type checking on instancetype methods, forcing use of casts like this:
[(SpringBoard *)[%c(SpringBoard) sharedApplication] doThing];
((SpringBoard *)[%c(SpringBoard) sharedApplication]).isThingDone; // even worse!Clang supports a weak_import attribute on classes that allows us to skip the linker trying to find the symbol to link, and allows the symbol to be optional just as %c() is.
Which would allow much more elegant code, like maybe:
%weakclass SpringBoard;
// …
[[SpringBoard sharedApplication] doThing];
[SpringBoard sharedApplication].isThingDone;%weakclass X would expand to:
__attribute__((weak_import))
@interface SpringBoard ()
@endOf course these weak symbols will be resolved at process launch time/library load time just like every other symbol dyld needs to resolve, so %c() is still necessary for late-loaded symbols.
To discuss:
Does this work on a category interface? Worst case scenario, we generate a separate file containing flags to pass the linker for weak import, or use this:
asm(".weak_reference _OBJC_CLASS_$_SpringBoard");According to this thread the attribute method may require a linker flag anyway due to a limitation of the implementation. I’m really hoping this is a bug and that it’s fixed now, so we can use an #if directive to check the clang version and #error out if it’s a known broken version.