如何找出objc_msgSend
的结果类型?
来自文档:
id objc_msgSend(id theReceiver, SEL theSelector, ...)
即objc_msgSend
返回的所有内容都属于id
类型,对吧?但有时函数返回一个正确的Objective C对象(当要求NSWindow + new时),有时它只返回一个bool(这是一个C char
)。
如何区分这些不同的结果?我怎么知道它是返回对象还是原始类型?
编辑:感谢您的回复!还有一个问题:是不是至少可以判断返回的类型是原始类型还是正确的对象(然后可能通过object_getClass
查询它)?
答案 0 :(得分:8)
objc_msgSend
的调用者应该已经知道返回的类型,并且必须有效地将objc_msgSend
强制转换为返回正确值的函数指针类型。例如,-[NSString UTF8String]
将手动调用,如下所示:
const char *cStr = ((const char *(*)(id, SEL))objc_msgSend)
(@"foo", @selector(UTF8String));
是的,非常满口,这就是为什么让编译器这样做更好的主意。如果您在发送消息时需要更多动态,我建议先查看NSInvocation。除其他外,初始化调用的方法签名将包括有关返回类型和所有参数的信息。
答案 1 :(得分:5)
您只能从方法签名中知道它。此外,返回浮点数时,objc_msgSend_fpret
以及返回结构时,将使用objc_msgSend_stret
。
如果返回的值是Objective-C对象,则可以使用object_getClass()
查询其类。
答案 2 :(得分:5)
如果这是返回类型的运行时发现,则可以使用ObjC运行时API查找给定对象方法的方法定义,然后返回类型。特别是方法:
Method class_getInstanceMethod(Class aClass, SEL aSelector)
或
Method class_getClassMethod(Class aClass, SEL aSelector)
将为您提供Method
结构,您可以随后使用
void method_getReturnType(Method method, char *dst, size_t dst_len)
获取返回类型的cstring描述。此描述不是人类可读的 - 例如,根据您的示例,您需要检查*dst
中引用的字符串是否等于“@”。如果是,则返回类型为id
类型。您可以看到对不同类型编码here的引用,以及我提到的here的ObjC运行时API方法。
正如H2C03所提到的,当从objc_msgSend_fpret
推断的返回类型表明它们的使用是合适的时(例如,当返回类型为a时),应使用objc_msgSend_stret
和method_getReturnType
变体。 struct或float。请参阅ObjC Runtime API文档页面上关于这两种方法的文档说明。)
另外,因为我希望你有一个美好的一天,我觉得我应该警告你关于运行时代码发现通常有点脆,通常是令人讨厌的性能气味。无论如何。 :)