【问题标题】:How to get the function name of a method in Objective-C?如何在 Objective-C 中获取方法的函数名?
【发布时间】:2011-02-28 01:37:30
【问题描述】:

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

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

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

【问题讨论】:

    标签: objective-c c function methods name-mangling


    【解决方案1】:

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

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

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

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

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

    您可以通过使用 C 函数 class_getMethodImplementation 或使用 +instanceMethodForSelector:(或 -methodForSelector:,如果您想允许可能在运行时重新排列其方法的特定实例)方法获取 IMP 指针在任何从 NSObject 派生的东西上。

    所以,例如

    #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));
    

    【讨论】:

      【解决方案2】:

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

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

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

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

      [anObject performSelector:aSelector];
      

      【讨论】:

      • 将此与我给出的答案进行对比:保留选择器是在您和您想要在 Objective-C 中调用的东西之间保持一定程度的间接性的正常方法。您可以在 C 函数之间传递一个 id 和一个 SEL,只需跳入编译为 Objective-C 的文件中的 C 函数即可进行相关调用。如果您有一些预先存在的 C 源代码,它只需要一个用户提供的信息的 'void *' 指针,那么由 id + SEL 组成的结构是一个很好的方法。一直丢弃到 C 调用最终看起来很丑陋,并且会丢失所有 Obj-C 调度。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-18
      • 2011-03-16
      • 2021-11-28
      • 2010-09-19
      • 1970-01-01
      相关资源
      最近更新 更多