【问题标题】:How do I inspect a Class in Objective-C?如何检查 Objective-C 中的类?
【发布时间】:2009-12-11 19:54:49
【问题描述】:

更新我通过实施Mark 的建议修复了代码,以消除覆盖方法的重复并跟踪属性或方法的创建者。还没有处理属性类型(当我这样做时可能会以property_getAttributes() 开头)。还去掉了残留的下划线。


基本上,我需要一种方法来提醒自己在给定对象上哪些方法和属性可用,而无需一直跳到继承树下。

我已经编写了以下函数,但还有一些不足之处:

#import <objc/runtime.h>

NSInteger inspectClass_alphabeticSort(id string1, id string2, void *reverse)
{
    if ((NSInteger *)reverse == NO)
    {
        return [string2 localizedCaseInsensitiveCompare:string1];
    }
    return [string1 localizedCaseInsensitiveCompare:string2];
}

void inspectClassStopAt(Class inspectedClass, Class stopClass)
{
    Class originalClass             = inspectedClass;
    NSString *originalClassString   = [NSString stringWithFormat:@"%@", originalClass];
    NSString *inheritancePath       = [NSString stringWithFormat:@"%@", originalClass];

    Method *methods;
    objc_property_t *properties;
    unsigned int i;
    unsigned int methodCount;
    unsigned int propertyCount;
    int reverseSort = NO;

    NSArray *sorted;
    NSArray *methodsAndPropertiesKeys;
    NSMutableDictionary * methodsAndProperties = [NSMutableDictionary dictionaryWithCapacity:10];

    NSString *inspectedClassString;
    NSString *methodOrPropertyName;
    while (inspectedClass != stopClass)
    {
        inspectedClassString = [NSString stringWithFormat:@"%@", inspectedClass];
        if (inspectedClass != originalClass)
        {
            inheritancePath = [inheritancePath stringByAppendingFormat:@" : %@", inspectedClass];
        }

        methods     = class_copyMethodList(inspectedClass, &methodCount);
        properties  = class_copyPropertyList(inspectedClass, &propertyCount);

        for (i=0; i<methodCount; i++)
        {
            methodOrPropertyName = [NSString stringWithFormat:@"-%s", sel_getName(method_getName(methods[i]))];

            if (![methodsAndProperties objectForKey:methodOrPropertyName])
            {
                [methodsAndProperties setObject:inspectedClassString forKey:methodOrPropertyName];
            }
        }

        for (i=0; i<propertyCount; i++)
        {
            methodOrPropertyName = [NSString stringWithFormat:@" %s", property_getName(properties[i])];

            if (![methodsAndProperties objectForKey:methodOrPropertyName])
            {
                [methodsAndProperties setObject:inspectedClassString forKey:methodOrPropertyName];
            }
        }

        inspectedClass = [inspectedClass superclass];
    }
    free(methods);
    free(properties);

    methodsAndPropertiesKeys = [methodsAndProperties allKeys];
    sorted = [methodsAndPropertiesKeys sortedArrayUsingFunction:inspectClass_alphabeticSort context:&reverseSort];

    NSLog(@"%@", inheritancePath);
    for (NSString *key in sorted)
    {
        if (![[methodsAndProperties objectForKey:key] isEqualToString:originalClassString])
        {
            NSLog(@"\t%@ (%@)", key, [methodsAndProperties objectForKey:key]);
        }
        else
        {
            NSLog(@"\t%@", key);
        }
    }
}

void inspectClass(Class inspectedClass)
{
    inspectClassStopAt(inspectedClass, [NSObject class]);
}

还有来自inspectClass([TextMap class]);的一些示例输出:

TextMap : Surface
     position (Surface)
     size (Surface)
    -addChild: (Surface)
    -dealloc
    -init (Surface)
    -initWithFile:
    -position (Surface)
    -render
    -setPosition: (Surface)
    -setSize: (Surface)
    -setText:
    -size (Surface)
    -update (Surface)

【问题讨论】:

  • 这个的用例是什么?我可以看到它在调试器控制台中很有用,除了在那里,您可以执行代码完成以获取相同的信息。
  • 我对 Objective-C 还是比较陌生,所以我正在迭代。很多。不是为了改进或重构代码,而是为了让它工作。属性和方法签名与我最初的期望和设计相比发生了很大变化。能够只转储一个类的当前签名而不必点击三个或四个源文件来拼凑一张清晰的图片会很好。由于从 NSObject 继承的所有非特定方法和属性,代码完成对我不起作用。
  • 看来这个问题的答案就在问题中!不错的作品。这帮了我很多忙。

标签: objective-c oop reflection


【解决方案1】:

runtime.h 提供的 c 库的一个很好的帮助器/包装器是 https://github.com/mikeash/MAObjCRuntime

我刚刚开始使用它,但它看起来很有希望。

就用例而言,我只是提供一个检查器来构建一个可以附加到对象图的自接线 UI。这有很多潜在的重复代码减少。

【讨论】:

    【解决方案2】:

    似乎您需要的是一个 NSMutableDictionary,以选择器名称为键。将每个选择器名称作为键添加到字典中,类名称作为值。您可以在添加选择器之前搜索字典,以消除重复。

    【讨论】:

      猜你喜欢
      • 2016-12-19
      • 2012-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多