How do I return a struct value from a runtime-defined class method under ARC?

本秂侑毒 提交于 2019-11-29 04:23:24

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.

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!