1

I have the following method. I currently use try/catch blocks to determine whether the argument is a class or a protocol, and it seems like it's causing a memory leak. What's the correct way to determine whether x is a class or a protocol?

[self _injectMacro:[MyClass class]];
[self _injectMacro:@protocol(MyProtocol)];

+ (id)_injectMacro:(id)x
{
    @try {
        return NSStringFromProtocol(x);
    }
    @catch (NSException *exception) {

    }

    @try {
        return NSStringFromClass(x);
    }
    @catch (NSException *exception) {

    }

    return nil;
}
jscs
  • 63,694
  • 13
  • 151
  • 195
aryaxt
  • 76,198
  • 92
  • 293
  • 442
  • Neither method documents what occurs if the class/protocol does not exist. Even if your code works today it might not tomorrow. – Hot Licks Feb 10 '14 at 00:59
  • Cocoa is not, in general, exception-safe. Continuing after catching may cause problems -- such as memory leaks. On the other hand, those functions don't throw exceptions as far as I know. Does this code actually do what you expect? – jscs Feb 10 '14 at 01:08
  • @JoshCaswell Thanks. You are right my code was alway going through the first try, and it was valid. When i switched the place of the two try-and-catch it started throwing EXC_Bad_Access, so it's not really catching the exception – aryaxt Feb 10 '14 at 01:34
  • 1
    I'd be surprised if those functions didn't just call straight through to the appropriate runtime functions, `class_getName()` and `protocol_getName()`, both of which try to dereference their argument, e.g., `return proto->name;` – jscs Feb 10 '14 at 01:39

1 Answers1

3

You can use isKindOfClass to find whether or not an id is a protocol:

id x = [NSObject class];
id y = @protocol(NSObject); 
NSLog(@"%d", [x isKindOfClass:[Protocol class]]); // 0
NSLog(@"%d", [y isKindOfClass:[Protocol class]]); // 1

You have to import the ObjectiveC.Protocol module to use Protocol:

@import ObjectiveC.Protocol;

Or if you are not using modules, just import the Protocol header:

#import <objc/Protocol.h>

To check if an id is a class or an instance have a look a this answer

Community
  • 1
  • 1
Sebastian
  • 7,670
  • 5
  • 38
  • 50
  • Getting a compile error on that import. Unexpected '@' in program – aryaxt Feb 10 '14 at 01:26
  • 2
    That's the new module syntax. Try `#import `, @aryaxt. – jscs Feb 10 '14 at 01:39
  • @JoshCaswell doesn't seem to work, did it work for you? – aryaxt Feb 10 '14 at 01:43
  • @JoshCaswell Thanks, I had to set 'enable module' to YES in build setting. It means any project that needs to use the code has to do the same. I'm wondering if there is another way. I'll use it for now. Thanks again for the quick answers – aryaxt Feb 10 '14 at 01:49
  • @aryaxt: As Josh pointed out, you can use the old `#import` syntax. I've updated my answer. – Sebastian Feb 10 '14 at 02:29