【问题标题】:Get all methods of an Objective-C class or instance获取 Objective-C 类或实例的所有方法
【发布时间】:2011-01-06 20:56:28
【问题描述】:

在 Objective-C 中,我可以测试给定的类或实例是否响应某些选择器。但是如何查询一个类或实例的所有方法或类的属性(例如所有方法或属性的列表)?

【问题讨论】:

    标签: objective-c introspection objective-c-runtime


    【解决方案1】:

    这可以通过 objc_method_list 实现。为了枚举您的方法,您必须事先注册所有方法。

    这个过程很简单:在你声明你的函数之后,你可以创建一个 objc_method 的实例并注册函数名。然后将 objc_method 添加到 objc_method_list 中,最后将 objc_method_list 传递给 class_addMethods..

    这是一个帮助您入门的链接: http://theocacao.com/document.page/327

    【讨论】:

      【解决方案2】:

      您需要使用 Objective C 运行时方法,请参见此处:https://developer.apple.com/reference/objectivec/objective_c_runtime

      【讨论】:

      • 此链接现在重定向到导航页面
      • 苹果文档变得更可怕了。 Buzzy 下面的答案是一个更好的答案。
      【解决方案3】:

      您可以做到这一点,它在https://developer.apple.com/library/mac/documentation/cocoa/Reference/ObjCRuntimeRef/index.html 上有很好的记录

      要获取一个类的所有实例或类方法,您可以使用class_copyMethodList 并遍历结果。一个例子:

       #import <objc/runtime.h>
      
      /**
       *  Gets a list of all methods on a class (or metaclass)
       *  and dumps some properties of each
       *
       *  @param clz the class or metaclass to investigate
       */
      void DumpObjcMethods(Class clz) {
      
          unsigned int methodCount = 0;
          Method *methods = class_copyMethodList(clz, &methodCount);
      
          printf("Found %d methods on '%s'\n", methodCount, class_getName(clz));
      
          for (unsigned int i = 0; i < methodCount; i++) {
              Method method = methods[i];
      
              printf("\t'%s' has method named '%s' of encoding '%s'\n",
                     class_getName(clz),
                     sel_getName(method_getName(method)),
                     method_getTypeEncoding(method));
      
              /**
               *  Or do whatever you need here...
               */
          }
      
          free(methods);
      }
      

      您需要对该方法进行两次单独的调用。一个用于实例方法,另一个用于类方法:

      /**
       *  This will dump all the instance methods
       */
      DumpObjcMethods(yourClass);
      

      在元类上调用相同的方法会给你所有的类方法

      /**
       *  Calling the same on the metaclass gives you
       *  the class methods
       */
      DumpObjcMethods(object_getClass(yourClass) /* Metaclass */);
      

      【讨论】:

      • 导入路径难找,使用:#import
      • 谢谢,可能是错字,“DumpObjcMethods(object_getClass(yourClass) /* Metaclass /);”应该是:“DumpObjcMethods(object_getMetaClass(yourClass) / Metaclass */);”
      • @Joey:我不认为那里有错字。没有名为object_getMetaClass 的例程。类对象类是它的元类。
      【解决方案4】:

      除了 Buzzy 的回答,出于调试目的,您可以使用 -[NSObject _methodDescription] 私有方法。

      在 lldb 中:

      (lldb) po [[UIApplication sharedApplication] _methodDescription]
      

      或在代码中:

      @interface NSObject (Private)
      - (NSString*)_methodDescription;
      @end
      
      // Somewhere in the code:
      NSLog(@"%@", [objectToInspect performSelector:@selector(_methodDescription)]);
      

      输出将如下所示:

      <__NSArrayM: 0x7f9 ddc4359a0>:
      in __NSArrayM:
          Class Methods:
              + (BOOL) automaticallyNotifiesObserversForKey:(id)arg1; (0x11503b510)
              + (id) allocWithZone:(_NSZone*)arg1; (0x11503b520)
              + (id) __new:::::(const id*)arg1; (0x114f0d700)
          Instance Methods:
              - (void) removeLastObject; (0x114f669a0)
              - (void) dealloc; (0x114f2a8f0)
              - (void) finalize; (0x11503b2c0)
              - (id) copyWithZone:(_NSZone*)arg1; (0x114f35500)
              - (unsigned long) count; (0x114f0d920)
              - (id) objectAtIndex:(unsigned long)arg1; (0x114f2a730)
              - (void) getObjects:(id*)arg1 range:(_NSRange)arg2; (0x114f35650)
              - (void) addObject:(id)arg1; (0x114f0d8e0)
              - (void) setObject:(id)arg1 atIndex:(unsigned long)arg2; (0x114f99680)
              - (void) insertObject:(id)arg1 atIndex:(unsigned long)arg2; (0x114f0d940)
              - (void) exchangeObjectAtIndex:(unsigned long)arg1 withObjectAtIndex:(unsigned long)arg2; (0x114f8bf80)
              ......
      in NSMutableArray:
          Class Methods:
              + (id) copyNonRetainingArray; (0x11ee20178)
              + (id) nonRetainingArray; (0x11ee201e8)
              + (id) nonRetainingArray; (0x120475026)
              + (id) arrayWithCapacity:(unsigned long)arg1; (0x114f74280)
              ......
      

      【讨论】:

      • 迄今为止的最佳答案
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-18
      • 2020-02-10
      • 1970-01-01
      • 1970-01-01
      • 2012-10-21
      相关资源
      最近更新 更多