Reputation: 44876
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
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
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
Reputation: 104065
Upvotes: 3