Steven Fisher
Steven Fisher

Reputation: 44876

Objective-C dynamic_cast?

Is there an Objective-C equivalent of C++'s dynamic_cast?

It can be faked using this:

MyClass *safeObject = [object isKindOfClass: [MyClass class]]
                      ? (MyClass *)originalObject : nil;

But this is a lot of code to type, even if I don't need to type it often.

I am a bit rusty so this might not be quite right, but I believe the equivalent in C++ would be:

MyClass safeObject = dynamic_cast<MyClass>(orginalObject);

The context here is a block where the parameter is defined as a type of a more generic class, but in this block I "know" it's a specific subclass. Nevertheless, I don't want to just cast it blindly with (MyClass *)originalObject and ignore a theoretically possible error.

To be clear, while I'd love a dynamic_cast, I'd be happy with an alternate approach to safely handle this case as well.

Upvotes: 15

Views: 7555

Answers (3)

Lily Ballard
Lily Ballard

Reputation: 185681

If you're willing to use Objective-C++, you can write this pretty easily:

template<typename T> inline T* objc_cast(id from) {
    if ([from isKindOfClass:[T class]]) {
        return static_cast<T*>(from);
    }
    return nil;
}

This should behave exactly as dynamic_cast<> except for obj-c objects.


If you want to stick with vanilla Obj-C you can get similar behavior with a class method on NSObject:

@interface NSObject (Cast)
+ (instancetype)cast:(id)from;
@end

@implementation NSObject (Cast)
+ (instancetype)cast:(id)from {
    if ([from isKindOfClass:self]) {
        return from;
    }
    return nil;
}
@end

This version just isn't as nice to use since you have to say something like

UIButton *button = [UIButton cast:someView];

In both versions the resulting value is nil if the cast fails.

Upvotes: 21

user529758
user529758

Reputation:

Try this macro:

#define objc_dynamic_cast(obj, cls) \
    ([obj isKindOfClass:(Class)objc_getClass(#cls)] ? (cls *)obj : NULL)

And also don't forget to

#include <objc/runtime.h>

Use it like:

MyClass *safeObject = objc_dynamic_cast(originalObject, MyClass);

Upvotes: 9

zoul
zoul

Reputation: 104065

  1. I don't think there is.
  2. I think the space for a bug is quite small here.
  3. But if you insist, a macro will do fine?

Upvotes: 3

Related Questions