【问题标题】:Retrieving property list of a class in iOS在 iOS 中检索类的属性列表
【发布时间】:2014-07-21 19:24:06
【问题描述】:

我正在尝试检索我的类或其任何子类定义的所有属性的列表。下面的代码sn -p是我一直在用的代码,一直到最近的iOS8 beta 4都可以正常运行。

if(!dictionary) {
    dictionary = [NSMutableDictionary dictionary];

    // Get all properties we have until we hit CBLNestedModel
    while(klass != [CBLNestedModel class]) {
        unsigned count;
        objc_property_t* properties = class_copyPropertyList(klass, &count);
        for (unsigned i = 0; i < count; i++) {
            objc_property_t property = properties[i];

            const char* propertyNameC = property_getName(property);
            NSString* propertyName = [NSString stringWithUTF8String:propertyNameC];
            const char* propertyAttrC = property_getAttributes(property);
            NSString* propertyAttrS = [NSString stringWithUTF8String:propertyAttrC];
            NSArray* propertyAttr = [propertyAttrS componentsSeparatedByString:@","];
            NSLog(@"%@ has property %@", NSStringFromClass(klass), propertyName);

            dictionary[propertyName] = propertyAttr;
        }
        free(properties);
        klass = [klass superclass];
    }

    propertyDictionary[klassString] = dictionary;
}

CBLNestedModel 派生自 NSObject。基本上,我想要 CBLNestedModel 的任何子类或其子类声明的所有属性。我面临的问题是,现在,此代码正在返回未在我的子类中定义的无关属性。对于某些类,propertyNames 以@"superclass", @"description", @"debugDescription", @"hash" 返回,即使我从未在我的子类中的任何地方定义这些属性.

奇怪的是,这些无关的属性并没有为 CBLNestedModel 的所有子类返回,而只是为某些子类返回。但是,每次运行我的应用程序时,这些子类都会可靠地返回它们。

知道为什么现在会发生这种情况吗?

【问题讨论】:

  • 这里有同样的问题。这很奇怪,因为superclass、description、debugDescription & hash 不是属性,而是NSObjectProtocol 由NSObject 实现的方法。第一个问题:这是一个错误吗?第二个:我们应该创建一个雷达吗?
  • 是的,这一定是一个错误。此代码在 iOS7 中完美运行。让我们通过 bugreport.apple.com 提交错误报告。希望报告此问题的人越多,他们将在下一次更新时修复它。
  • @Martin @rvijay007 这不是错误,它们现在是 iOS 8 中的属性。问题是为什么它们只出现在 一些 子类中。我遇到了同样的问题,但是我有一个 XC 测试用例,它的对象是 NSObject 的直接子类,在调用属性方法时不会显示这些对象。但我有一个不同的对象,另一个直接子类,在应用程序的正常运行期间确实返回hash、description、superclass 和debugDescription。你能分享更多关于你的子类可能有助于发现问题的信息吗?还是报告的更新?
  • 我遇到了同样的问题,而且它仅适用于某些课程。我不完全确定为什么它只有一些类。你有想过吗?
  • @odyth 我可能已经想通了,并在下面发布了我的答案。

标签: objective-c ios8 nsobject objective-c-runtime


【解决方案1】:

您的CBLNestedModel 子类是否遵守任何协议?我之前看到过与我拥有的对象类似的问题,但无法弄清楚为什么出现了 hash、description、superclass 和 debugDescription,我终于弄明白了。这是我所拥有的:

@interface FOOObject : NSObject<NSCopying, FOOOtherProtocol>

看起来不错,它是NSObject 的直接子类。事实上,我还有其他对象来测试它,一个有属性,一个没有。

@interface FOOObjectWithProperties : NSObject

@property NSString *someProperty;

@end

和

@interface FOOObjectWithoutProperties : NSObject
@end

在测试期间FOOObjectWithProperties 和FOOObjectWithoutProperties 都没有包含上述四个NSObject 属性,但原来的FOOObject DID。 p>

那么有什么区别呢?看看NSCopying,它似乎没有添加任何属性,所以我查看了FOOOtherProtocol,这是我实现的一些协议,它也没有声明任何属性。

但是

看FOOOtherProtocol的声明:

@protocol FOOOtherProtocol<NSObject>

就在那里。 Objective-c 运行时的东西确实不在返回的内容中包含超类属性,但是它将包含在协议扩展(强制遵守其他协议的协议)中声明的属性。

注意到关于hash、description、superclass 和debugDescription 的任何信息?

查看它们在NSObject protocol declaration 中的声明位置

从您的子类的协议中移除强制遵守的NSObject 协议(因为无论如何它们都是已经遵守它的 NSObject 的子类),您应该会看到这些属性消失了。

【讨论】:

  • 我认为你一针见血。我的代码中存在问题的类最终具有符合 NSObject 协议的协议。很好的发现。
  • @odyth 谢谢!花了一些时间挖掘哈哈,但现在我知道了,感觉就像我知道了魔术的秘密;一种苦乐参半的满足。
【解决方案2】:

在 iOS 8 上,这 4 个方法现在在 NSObject 中被声明为只读属性。

More info here.

【讨论】:

    猜你喜欢
    • 2018-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-13
    • 2015-06-23
    • 1970-01-01
    • 2020-08-26
    • 2011-06-01
    相关资源
    最近更新 更多