Let's say I have an uninitialized variable:
UIViewController *vc;
From this variable, I want to reference UIViewController
, such that I could call alloc
or new
on it to return an instantiated object.
Essentially, I want to do:
UIViewController *vc = [*typeof(vc) new];
... which does not compile because the compiler expects an expression rather than a type.
If @encode
returned the actual type, I could do something like:
UIViewController *vc = [NSClassFromString(@(@encode(*typeof(vc)))) new];
...however, @encode
returns '@', which just means "generic object".
I realize it's a little philosophical in nature, but I get tired of typing and would like to make a macro like NEW(x)
. I also realize a similar macro could be made if it involves the actual declaration, but I am not satisfied with that syntax/angle.
Here's what I have... it doesn't seem ideal, since it makes a performance hit. Still looking for better answers.
static Class classFromEncoding(const char *encoding) {
char *className = strndup(encoding + 1, strchr(encoding, '=') - encoding - 1);
Class retval = NSClassFromString(@(className));
free(className);
return retval;
}
#define NEW(variable) [classFromEncoding(@encode(typeof(*variable))) new]
Here's a macro-only version:
#define CLASS_FROM_VARIABLE(variable) \
^(const char *encoding) { \
char *className = strndup(encoding + 1, strchr(encoding, '=') - encoding - 1); \
Class retval = NSClassFromString(@(className)); \
free(className); \
return retval; \
}(@encode(typeof(*variable)))
#define NEW(variable) [CLASS_FROM_VARIABLE(variable) new]
#define ALLOC(variable) [CLASS_FROM_VARIABLE(variable) alloc]
Variations can be made using objc_getClass() or NSString initWithBytes, perhaps with performance gains. Still, it's not a no-op, which is what I'd prefer.