Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective-C Safe Casting Macro

I've written a macro in Objective-C to perform a safe cast. Here's what it looks like so far:

#define SAFE_CAST(OBJECT, TYPE) ([OBJECT isKindOfClass:[TYPE class]] ? (TYPE *) OBJECT: nil)

This works really well, but it'd be nice if there was a way to store OBJECT in a variable so it didn't get called twice. For instance, using the macro as such:

NSString *str = SAFE_CAST([dictinary objectForKey:key], NSString);

results in code similar to this when the macro is expanded:

NSString *str = ([[dictinary objectForKey:key] isKindOfClass:[NSString class]] ? (NSString *) [dictinary objectForKey:key]: nil);

I'd prefer for it to work more like this:

id obj = [dictionary objectForKey:key];
NSString *str = ([obj objectForKey:key] isKindOfClass[NSString class]] ? (NSString *) obj : nil);

Thanks.

like image 559
LandonSchropp Avatar asked Jul 13 '10 02:07

LandonSchropp


2 Answers

You can use a GCC extension called statement statement expressions to have

#define SAFE_CAST(OBJECT, TYPE) ({ id obj=OBJECT;[obj isKindOfClass:[TYPE class]] ? (TYPE *) obj: nil; })

That said, I think it's generally a bad approach to have a situation where you need to use SAFE_CAST a lot. Never put objects of different classes in an array; never reuse an action message (IBAction)someAction:(id)sender for UI objects of different classes. Then you usually don't need to use SAFE_CAST.

like image 168
Yuji Avatar answered Oct 14 '22 13:10

Yuji


If you really think you must do this, you could use a function:

#define SAFE_CAST(Object, Type) (Type *)cast_helper(Object, [Type class])
static id cast_helper(id x, Class c) {
    return [x isKindOfClass:c] ? x : nil;
}
like image 33
Georg Fritzsche Avatar answered Oct 14 '22 12:10

Georg Fritzsche