如何找到符合KVC标准的Objective-C对象的所有属性键?

时间:2009-04-23 09:11:00

标签: objective-c cocoa properties introspection key-value-observing

是否有方法返回符合NSKeyValueCoding协议的对象的所有密钥?

[object getPropertyKeys]的某些内容将返回NSString对象的NSArray。它适用于任何符合KVC标准的对象。这种方法存在吗?到目前为止,我还没有找到任何搜索Apple文档的内容。

谢谢, -G。

5 个答案:

答案 0 :(得分:36)

#import "objc/runtime.h"

unsigned int outCount, i;

objc_property_t *properties = class_copyPropertyList([self class], &outCount);
for(i = 0; i < outCount; i++) {
    objc_property_t property = properties[i];
    const char *propName = property_getName(property);
    if(propName) {
            const char *propType = getPropertyType(property);
            NSString *propertyName = [NSString stringWithUTF8String:propName];
            NSString *propertyType = [NSString stringWithUTF8String:propType];
    }
}
free(properties);

答案 1 :(得分:3)

使用class_getPropertyList。这将告诉你对象的所有@properties

它不一定列出每个符合KVC的属性,因为任何不带参数并返回值的方法都是有效的KVC兼容的getter。运行时没有100%可靠的方式来知道哪些行为属性(例如-[NSString length])以及哪些行为作为命令(例如-[NSFileHandle readDataToEndOfFile])。

无论如何,您应该将符合KVC标准的属性声明为@properties,因此这不应该是一个太大的问题。

答案 2 :(得分:1)

没有这样的方法,因为KVO系统不需要对象/类向其注册它们支持KVO的属性。 任何键都可能支持KVO,唯一可以通过作者的文档获知。

当然,不能保证@property会支持KVO;写一个没有(有时可能是必要的)的财产是很有可能的。因此,在我看来,获取一个类@property的列表然后假设它们符合KVO将是一个危险的选择。

答案 3 :(得分:0)

您需要一个getPropertyType函数。请参阅此帖子:Get an object attributes list in Objective-C

答案 4 :(得分:-1)

对于Swift旁观者,您可以使用Encodable功能获得此功能。我将解释如何:

  1. 使您的对象符合Encodable协议

    class ExampleObj: NSObject, Encodable {
        var prop1: String = ""
        var prop2: String = ""
    }
    
  2. Encodable创建扩展程序以提供toDictionary功能

     public func toDictionary() -> [String: AnyObject]? {
        let encoder = JSONEncoder()
        encoder.outputFormatting = .prettyPrinted
        guard let data =  try? encoder.encode(self),
              let json = try? JSONSerialization.jsonObject(with: data, options: .init(rawValue: 0)), let jsonDict = json as? [String: AnyObject] else {
            return nil
        }
        return jsonDict
    }
    
  3. 在对象实例上调用toDictionary并访问keys属性。

    let exampleObj = ExampleObj()
    exampleObj.toDictionary()?.keys
    
  4. 瞧!像这样访问您的属性:

    for k in exampleObj!.keys {
        print(k)
    }
    // Prints "prop1"
    // Prints "prop2"