I have a class method returning a CGSize
and I\'d like to call it via the Objective-C runtime functions because I\'m given the class and method names as string
If you wish to retrieve a struct from your class method, you can use an NSInvocation as follows:
Class clazz = NSClassFromString(@"MyClass");
SEL aSelector = NSSelectorFromString(@"testMethod");
CGSize returnStruct; // Or whatever type you're retrieving
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[clazz methodSignatureForSelector:aSelector]];
[invocation setTarget:clazz];
[invocation setSelector:aSelector];
[invocation invoke];
[invocation getReturnValue:&returnStruct];
At the end of this, returnStruct
should contain your struct value. I just tested this in an ARC-enabled application and this works fine.
You need to cast objc_msgSend_stret
to the correct function pointer type. It's defined as void objc_msgSend_stret(id, SEL, ...)
, which is an inappropriate type to actually call. You'll want to use something like
CGSize size = ((CGSize(*)(id, SEL, NSString*))objc_msgSend_stret)(clazz, @selector(contentSize:), text);
Here we're just casting objc_msgSend_stret to a function of type (CGSize (*)(id, SEL, NSString*))
, which is the actual type of the IMP
that implements +contentSize:
.
Note, we're also using @selector(contentSize:)
because there's no reason to use NSSelectorFromString()
for selectors known at compile-time.
Also note that casting the function pointer is required even for regular invocations of objc_msgSend()
. Even if calling objc_msgSend()
directly works in your particular case, it's relying on the assumption that the varargs method invocation ABI is the same as the ABI for calling a non-varargs method, which may not be true on all platforms.