如何在Objective-C中获取方法的函数名?

0 c methods function objective-c name-mangling

据我所知,一个方法被编译成这样的函数:

+(NSArray *)arrayWithObject:(id)object;
// becomes
NSArray *_c_NSArray_arrayWithObject_(id object);
Run Code Online (Sandbox Code Playgroud)

是否有可能获得选择器函数的名称,以便我可以将该方法作为参数传递给C函数,或者这是不可能的?

Tom*_*mmy 6

不完全 - 他们看起来像:

id method(id, SEL, ...); 
Run Code Online (Sandbox Code Playgroud)

因此,Objective-C方法(无论是类还是实例方法)都希望获取正在调用的类的实例(在类方法的情况下将是元类)和触发它的选择器.

这种类型被objc.h定义为'IMP':

typedef id          (*IMP)(id, SEL, ...); 
Run Code Online (Sandbox Code Playgroud)

您可以通过使用C函数class_getMethodImplementation或使用+ instanceMethodForSelector :(-methodForSelector : ,如果您希望允许特定实例可能已在运行时重新排列其方法)方法获取IMP指针NSObject的.

所以,例如

#import <objc/objc.h>

id someObject = ...something...;
IMP functionPointerToMethod = [someObject methodForSelector:@selector(method)];

functionPointerToMethod(someObject, @selector(method));
Run Code Online (Sandbox Code Playgroud)

要么:

IMP functionPointerToMethod = [someObject methodForSelector:@selector(method:)];
functionPointerToMethod(someObject, @selector(method:), argument);
Run Code Online (Sandbox Code Playgroud)

甚至:

IMP functionPointerToMethod = class_getMethodImplementation([someObject class],
                                                            @selector(method:));

functionPointerToMethod(someObject, @selector(method:), argument);
Run Code Online (Sandbox Code Playgroud)

当然,在所有这些中,您正在做的是从循环中删除Objective-C的正常动态分派.因此,如果您随后在类上添加或重新排列方法,那么您的C函数指针将变得过时.

类方法可以通过大致相同的方式访问,但是通过元类,例如

// to do the same as [NSString alloc], not that you ever would...
IMP functionPointerToAlloc = [[NSString class] methodForSelector:@selector(alloc)];
functionPointerToMethod([NSString class], @selector(alloc));
Run Code Online (Sandbox Code Playgroud)