Question

I have a condition where I want a view controller to conform to any of 4 protocols.

Is there a way to check if it conforms to any of these 4 protocols without doing a bunch of or statements in my if?

Can you make an array of protocols?

Was it helpful?

Solution

Sure, you can make an array of protocols:

NSArray *protocols = @[@protocol(UIApplicationDelegate),
    @protocol(UIImagePickerControllerDelegate),
    @protocol(UIScrollViewDelegate),
    @protocol(NSFileManagerDelegate)];

You could then check that some object conforms to all of them:

UIViewController *vc = ...;
for (Protocol *protocol in protocols) {
    if (![vc conformsToProtocol:protocol]) {
        NSLog(@"object doesn't conform to %@", protocol);
    }
}

It's hard to imagine why you'd want to do this at run-time, though.

Perhaps what you really want is to declare that something conforms to several protocols. You can do that too, and the compiler will check it for you at compile-time. For example:

@property (nonatomic, strong) id<UIApplicationDelegate, UIImagePickerController,
    UIScrollViewDelegate, NSFileManagerDelegate> swissArmyKnife;

If you try to assign something to this property, and it doesn't conform to all four protocols, the compiler will issue a warning.

Perhaps what you are saying is you want to verify that an object conforms to at least one of the protocols, but that it doesn't have to conform to all of them. In that case, you have to check at run-time. But that smells like a bad design to me.

If you want to send a message to the object, but you're not sure that it will understand the message, it's probably better to check specifically for the message you want to send, instead of checking for protocol conformance.

// This is probably not such a good idea.
if ([object conformsToProtocol:@protocol(NSFileManagerDelegate)]) {
    return [object fileManager:myFileManager shouldRemoveItemAtURL:url];
} else {
   return arc4random_uniform(2);
}


// This is probably better.
if ([object respondsToSelector:@selector(fileManager:shouldRemoveItemAtURL:)]) {
    return [object fileManager:myFileManager shouldRemoveItemAtURL:url];
} else {
   return arc4random_uniform(2);
}

OTHER TIPS

Sure.

id object = ...;
Protocol *protocols[] = {@protocol(Blah), @protocol(Foo), @protocol(Bar)};
for(unsigned i = 0; i < sizeof(protocols) / sizeof(Protocol *); ++i) {
   if([object conformsToProtocol:protocols[i]]) {
     //do something...
     break;
   }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top