I often find myself asserting that an object "isKindOfClass" of some class in Objective-C. I do it like this:
NSAssert([obj isKindOfClass:[AClass class]], @"%@ should be kind of class %@", obj, [[AClass class] description]);
I'm wondering about the best way to make a short-cut for it. I'm thinking about defining a macro, something like:
#define NSClassAssert(obj, class) NSAssert([obj isKindOfClass:class], @"%@ should be of class %@", obj, [class description])
I'm worried that this might cause some nasty intractable compile errors or run-time problems, is there anything fundamentally wrong with doing it this way, is there a plain better way to do it?
One has to ask exactly why you want to do this in the first place. You said:
Given how tolerant and dynamic objective c is, I like to make code "abuse proof". Instead of having an unrecognized selector message, I have a message telling me which class the object was expected to be.
If you pass an object to a method that does not match the type declared in the signature, i.e., you do something like this:
- (void)doSomething:(NSArray *)array { /* Do something * }
- (void)doSomethingElse
{
NSString *string = @"my string";
[self doSomething:string];
}
you'll get a warning, so you should know at compile time that the object types don't match.
Of course, this doesn't protect you when using a more generic type, such as id
, but if you're worried about unrecognized selectors, you really should check to see if a object responds to that selector, instead of using an assert:
- (id)doSomething:(id)obj
{
if ([obj respondsToSelector:@selector(calculateSomething)]) {
return [obj calculateSomething];
} else {
NSLog(@"%@ does not respond to calculateSomething", obj);
}
}
Or use protocols to check for the availability of methods.
However, that said, yes, your macro will work for your intended purpose.