Jasarien
Jasarien

Reputation: 58448

Checking whether an object conforms to two separate protocols in Objective-C

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

Answers (3)

Felipe Cypriano
Felipe Cypriano

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

Dave DeLong
Dave DeLong

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

user557219
user557219

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

Related Questions