0

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

+(NSArray *)arrayWithObject:(id)object;
// becomes
NSArray *_c_NSArray_arrayWithObject_(id object);

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

4

2 回答 2

6

不完全——它们看起来像:

id method(id, SEL, ...); 

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

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

typedef id          (*IMP)(id, SEL, ...); 

您可以通过使用 C 函数class_getMethodImplementation或使用+instanceMethodForSelector:(或-methodForSelector:,如果您想允许特定实例可能在运行时重新排列其方法)方法来获取 IMP 指针。 NS对象。

所以,例如

#import <objc/objc.h>

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

functionPointerToMethod(someObject, @selector(method));

或者:

IMP functionPointerToMethod = [someObject methodForSelector:@selector(method:)];
functionPointerToMethod(someObject, @selector(method:), argument);

甚至:

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

functionPointerToMethod(someObject, @selector(method:), argument);

当然,在这一切中,您所做的是从循环中删除 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));
于 2011-02-28T01:50:38.837 回答
2

您可以使用称为选择器的东西来传递方法的名称。选择器基本上是方法的名称,可以用来调用该方法。例如

SEL aSelector; 
aSelector = @selector(aMethod:);

这意味着您采用“aMethod:”方法,现在您可以在另一个函数的参数中传递该选择器(SEL 类型)。不确定这是否是您正在寻找的,但希望它有所帮助。

您还可以通过以下方式调用该方法:

[anObject performSelector:aSelector];
于 2011-02-28T01:46:00.987 回答