Objective C:objc_msgSend返回类型

时间:2012-07-01 21:31:40

标签: objective-c

如何找出objc_msgSend的结果类型?

来自文档:

id objc_msgSend(id theReceiver, SEL theSelector, ...)

objc_msgSend返回的所有内容都属于id类型,对吧?但有时函数返回一个正确的Objective C对象(当要求NSWindow + new时),有时它只返回一个bool(这是一个C char)。

如何区分这些不同的结果?我怎么知道它是返回对象还是原始类型?

编辑:感谢您的回复!还有一个问题:是不是至少可以判断返回的类型是原始类型还是正确的对象(然后可能通过object_getClass查询它)?

3 个答案:

答案 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_stretmethod_getReturnType变体。 struct或float。请参阅ObjC Runtime API文档页面上关于这两种方法的文档说明。)

另外,因为我希望你有一个美好的一天,我觉得我应该警告你关于运行时代码发现通常有点脆,通常是令人讨厌的性能气味。无论如何。 :)