I have the following method:
-(void)SomeMethod:(id)classOrProtocol;
It will be called like this:
[self someMethod:@protocol(SomeProtocol)];
Or
[self someMethod:[SomeClass class]];
Within the method body I need to decide if |classOrProtocol| is:
Any Class(Class) OR Any Protocol(Protocol) OR Anything else
[[classOrProtocol class] isKindOfClass: [Protocol class]]
Results in a (build)error:
Receiver 'Protocol' is a forward class and corresponding @interface may not exist
So how can I tell a Protocol from a Class from anything else?
In Objective-C 2 (i.e. unless you use 32 bit runtime on OS X) Protocol
is defined to be just a forward class, see /usr/include/objc/runtime.h
. The real interface is nowhere declared. You can try to include /usr/inlcude/objc/Protocol.h
by saying
#import <objc/Protocol.h>
but as is written there, no method is publicly supported for an instance of Protocol
. The only accepted way to deal with Protocol
instances is to use runtime functions, given in Objective-C Runtime Reference. It's not even publicly defined whether Protocol
is a subclass of anything, and it's not even stated that it implements NSObject
protocol. So you can't call any method on it.
Of course you can use the source code of the runtime to see what's going on. Protocol
inherits from Object
(which is a remnant from pre-OpenStep NeXTSTep), not from NSObject
. So you can't use the familiar methods for NSObject
-derived objects, including Class
of NSObject
-derived objects. See the opensourced implementations of Protocol.h and Protocol.m. As you see there, the class Protocol
itself doesn't do anything, because every method just casts self
to protocol_t
and calls a function. In fact, as can be seen from the function _read_images
and others in objc-runtime-new.mm
, the isa
pointer of a Protocol
object is set by hand when the executable and libraries are loaded, and never used.
So, don't try to inspect whether an id
is a Protocol
or not.
If you really need to do this, you can use
id foo=...;
if(foo->isa==class_getClass("Protocol")){
...
}
But, seriously, don't do it.