I’m trying code to an interface (or a protocol in Objective C terminology), not an implementation.
It’s critical that we check objects conform to protocol before calling methods on them to prevent crashes.
Three Ways
- In compiler
- At runtime
- Both
Best Solution… Surely Number 1?
I thought the best way would be in the compiler:
- Warnings ahoy if you screw up
- Eliminates conformsToProtocol:/respondsToSelector: boilerplate
- At runtime it’s too late if you made a mistake – the best you can do is not execute the code/show an error
But I see a lot of code that’s doing it at runtime. Why?
Is it a readability issue – needing id <Protocol> everywhere?
My Question
What’s the most robust and readable way of ensuring objects conform to a interface/protocol?
Code
1. Checking In Compiler
@interface ReportController : NSObject {
id <ReportGenerator> generator;
id <ReportSender> sender;
id report;
}
@implementation ReportController
-(id)initWithReportGenerator:(id <ReportGenerator>)generator_
reportSender:(id <ReportSender>)sender_ {
// Usual init stuff
generator = generator_;
sender = sender_;
return self;
}
-(void)generateAndSend {
report = [generator generate];
[sender sendReport:report];
}
@end
2. Checking At Runtime
@interface ReportController : NSObject {
id generator;
id sender;
id report;
}
@implementation ReportController
-(id)initWithReportGenerator:(id)generator_
reportSender:(id)sender_ {
// Usual init stuff
generator = generator_;
sender = sender_;
return self;
}
-(void)generateAndSend {
if ([generator conformsToProtocol:@protocol(ReportGenerator)] &&
[sender conformsToProtocol:@protocol(ReportSender)]) {
report = [generator generate];
[sender sendReport:report];
} else {
[NSException raise:NSInternalInconsistencyException format:@"Objects didn't respond to protocols..."];
}
}
@end
You should use both. Consider e.g.:
Objective-C and Cocoa are too dynamic to generally check such things at compile time (
NSProxystandins, classes dynamically adding methods and protocols, …).It is nice to catch as many of such errors at compile-time as possible, but that alone is not sufficient.