4

I'm writing a couple classes that make use of the Objective-C runtime library. This includes retrieving Protocol definitions at runtime based on their name. However, it appears that Protocols that are not explicitly adopted by a class or referenced in code using @protocol(ProtocolName) are excluded from compilation and not available at runtime.

Example:

@protocol MyProtocol <NSObject>

-(void)doSomething;

@end

//Somewhere else in code

Protocol *protocol = NSProtocolFromString(@"MyProtocol"); 
// ^ value of "protocol" will be nil when I run the application!

//However, if I use do the following:

Protocol *whyDoIHaveToDoThis = @protocol(MyProtocol);
Protocol *protocol = NSProtocolFromString(@"MyProtocol"); 
// ^ value of "protocol" will now be a pointer as expected when I run the application!

Does anyone know why this is, and even better, how to force the compiler to include Protocol definitions that are not in use at compile time, but which I will later want available at runtime?

Daniel Hall
  • 13,457
  • 4
  • 41
  • 37
  • 2
    It's the way it works. How can you use the protocol if there is no class that adopts it? – Hot Licks Feb 07 '14 at 01:58
  • This answer might be helpful: http://stackoverflow.com/a/11533804/342620 – Gabriel Roth Feb 07 '14 at 02:21
  • This is expected. The compiler emits no metadata for a protocol declaration, and emits a duplicate copy of the metadata in any file that uses the protocol (either by adopting it or by writing an `@protocol(ProtoName)` expression. – Greg Parker Feb 07 '14 at 02:56
  • Thanks for the comments, all. @Hot Licks - protocols can be analyzed and adopted at runtime using functions like class_addProtocol(). For libraries, plugins, and other types of code that need to interact with unknown "foreign" code at runtime, it's important that protocol definitions can be looked up on the fly, even if no internal objects have adopted them at compile time. I'm really surprised that protocol definitions are just stripped like this, when Objective-C is a dynamic language meant to be able to deal with unknown types, which is a main use of protocols in the first place. – Daniel Hall Feb 07 '14 at 15:17
  • But the protocol is mainly just documentation to the compiler to tell it what methods are available -- it has no real runtime function. class_copyMethodList will tell you what methods are there at runtime. – Hot Licks Feb 07 '14 at 16:50

1 Answers1

3

You can force the compiler to include the protocol by making a dummy method that's not called that uses it. I've done this before:

void preserveProtocolFromBeingTrimmed()
{
     (void)@protocol(BrightnessProtocol);
}

I see that Apple uses this in their FxBrightness plug-in from the FxPlug SDK.

user1118321
  • 25,567
  • 4
  • 55
  • 86
  • 1
    Thanks! I upvoted this for the link to the Apple example code. My hoped-for answer is something that forces the inclusion of Protocol definitions that "are not in use at compile time" which wouldn't be the case using the method above. I'm hoping for something more along the lines of a compiler flag, etc. that forces protocol headers that are included as compile targets to not be ignored if they are not in use, but I realize that such flag may not exist and your suggestion may be the best / only solution. If no better answer is presented, I'll accept yours :) – Daniel Hall Feb 07 '14 at 15:11