Search code examples
objective-cclassmacrosnsassert

Asserting object class in Objective C


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?


Solution

  • 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.