Reputation: 58448
In Objective-C when you declare an instance variable you can check if it conforms to a protocol on assignment at compile time like so:
id <MyProtocol> variable;
Is it possible to check whether an object assigned to the variable conforms to two separate protocols at compile time? As in:
id <MyProtocol, MyOtherProtocol> variable;
I know I can do runtime checking using conformsToProtocol:
and respondsToSelector
et al, (which I do before actually using the object for added safety), and I could write my own setter method that does the check, but I'd like to know at compile time.
Upvotes: 16
Views: 10486
Reputation: 2737
I think the best is to use your own code:
id <MyProtocol, MyOtherProtocol> variable;
And before calling a method, check if the variable responds to what you want to call:
if ([variable respondsToSelector:@selector(aMethod:)]) {
[variable aMethod:nil];
}
Since Objective-C is a dynamic language, just declaring the variable protocol can't assure that it conforms to the protocol. It'll mostly generates warnings when you build.
Upvotes: 13
Reputation: 243146
Yes, that syntax is correct.
The correct way to check if an object conforms to a protocol is to do this:
if ([myObj conformsToProtocol:@protocol(MyProtocol)]) {
//conformance!
}
Note that this works as both an instance method and a class method.
If for some bizarre reason you can't use the conformsToProtocol:
, you can drop down to the runtime level:
#import <objc/runtime.h>
Protocol * p = objc_getProtocol("MyProtocol");
if (class_conformsToProtocol([myObj class], p)) {
//conformance!
}
Upvotes: 58
Reputation:
You can’t always check protocol conformance in compile-time because an object of (non-qualified) type id
is always a valid object from the compiler’s perspective. For instance,
id<P1> p1;
id<P2> p2;
id p0;
// compiler warning: assigning to 'id<P1>' from incompatible type 'id<P2>'
p1 = p2;
// no compiler warning
p0 = p2;
p1 = p0;
That being said, <P1, P2>
will give you warnings in case the object doesn’t conform to both protocols if that can be known at compile-time:
id<P1> p1;
id<P2> p2;
id<P1, P2> p12;
id<P1, P2> q12;
id p0;
p12 = p1; // warning: assigning to 'id<P1,P2>' from incompatible type 'id<P1>'
p12 = p2; // warning: assigning to 'id<P1,P2>' from incompatible type 'id<P2>'
p12 = q12; // no compiler warning
// no compiler warning
p0 = p1;
p12 = p0;
Upvotes: 3