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

时间:2022-09-07 08:46:55

Is there a method that returns all the keys for an object conforming to the NSKeyValueCoding protocol?

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

Something along the lines of [object getPropertyKeys] that would return an NSArray of NSString objects. It would work for any KVC-compliant object. Does such a method exist? I haven't found anything in searching the Apple docs so far.

沿着[object getPropertyKeys]行返回NSString对象的NSArray。它适用于任何kvc兼容的对象。这种方法存在吗?到目前为止,我还没有在苹果文档中找到任何东西。

Thanks, G.

谢谢,G。

6 个解决方案

#1


33  

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

#2


3  

Use class_getPropertyList. That will tell you all the @properties of the object.

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

It won't necessarily list every KVC-compliant property, because any method that takes no arguments and returns a value is a valid KVC-compliant getter. There's no 100%-reliable way for the runtime to know which ones behave as properties (e.g., -[NSString length]) and which ones behave as commands (e.g., -[NSFileHandle readDataToEndOfFile]).

它不一定列出所有kvc兼容的属性,因为任何不接受参数并返回值的方法都是有效的kvc兼容的getter。运行时没有100%可靠的方法知道哪些属性(例如-[NSString length])和哪些属性作为命令(例如-[NSFileHandle readDataToEndOfFile])。

You should be declaring your KVC-compliant properties as @properties anyway, so this shouldn't be too big of a problem.

无论如何,您应该将kvc兼容的属性声明为@properties,因此这应该不是什么大问题。

#3


1  

There is no such method as the KVO system does not require objects/classes to register with it which properties they support KVO for. Any key could potentially support KVO, the only way to know is from the author's documentation.

没有这样的方法,例如KVO系统不需要对象/类向它注册它们支持KVO的属性。任何键都可能支持KVO,唯一的方法就是从作者的文档中知道。

And of course, there is no guarantee that an @property will support KVO; it's quite possible to write a property that doesn't (and may be necessary sometimes). So, getting a list of a class's @propertys and then assuming they're KVO-compliant would be a dangerous choice in my opinion.

当然,@property不能保证支持KVO;编写一个不需要的属性是很有可能的(有时可能是必需的)。因此,在我看来,得到一个类的@propertys列表,然后假设它们与kvos兼容是一个危险的选择。

#4


0  

You need a getPropertyType function. See this post: Get an object attributes list in Objective-C

您需要一个getPropertyType函数。请参阅本文:获取Objective-C中的对象属性列表

#5


0  

For Swift onlookers, you can get this functionality by utilising the Encodable functionality. I will explain how:

对于快速的旁观者,你可以通过使用可编码的功能来获得这个功能。我将解释如何:

  1. Conform your object to Encodable protocol

    使您的对象符合可编码协议

    class ExampleObj: NSObject, Encodable {
        var prop1: String = ""
        var prop2: String = ""
    }
    
  2. Create extension for Encodable to provide toDictionary functionality

    为Encodable创建扩展以提供字典功能

     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. Call toDictionary on your object instance and access keys property.

    在对象实例和访问键属性上调用toDictionary。

    let exampleObj = ExampleObj()
    exampleObj.toDictionary()?.keys
    
  4. Voila! Access your properties like so:

    瞧!访问您的属性如下:

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

#6


-1  

Environment:Xcode7.2,iOS9.2

环境:Xcode7.2 iOS9.2

I use code snippet below to get property names of a specified class,it works fine:

我使用下面的代码片段获取指定类的属性名,它工作得很好:

import "objc/runtime.h"

unsigned int outCount, i;

objc_property_t *properties = class_copyPropertyList([SNBankBean class], &outCount);
for(i = 0; i < outCount; i++) {
    objc_property_t property = properties[i];
    const char *propName = property_getName(property);
    if(propName) {
        NSString *propertyName = [NSString stringWithUTF8String:propName];
        NSLog(@"the property name is %@",propertyName);
        if ([propertyName isEqualToString:bank_name]) {
            self.isBankExisted=YES;
        }
    }
}
free(properties);

#1


33  

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

#2


3  

Use class_getPropertyList. That will tell you all the @properties of the object.

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

It won't necessarily list every KVC-compliant property, because any method that takes no arguments and returns a value is a valid KVC-compliant getter. There's no 100%-reliable way for the runtime to know which ones behave as properties (e.g., -[NSString length]) and which ones behave as commands (e.g., -[NSFileHandle readDataToEndOfFile]).

它不一定列出所有kvc兼容的属性,因为任何不接受参数并返回值的方法都是有效的kvc兼容的getter。运行时没有100%可靠的方法知道哪些属性(例如-[NSString length])和哪些属性作为命令(例如-[NSFileHandle readDataToEndOfFile])。

You should be declaring your KVC-compliant properties as @properties anyway, so this shouldn't be too big of a problem.

无论如何,您应该将kvc兼容的属性声明为@properties,因此这应该不是什么大问题。

#3


1  

There is no such method as the KVO system does not require objects/classes to register with it which properties they support KVO for. Any key could potentially support KVO, the only way to know is from the author's documentation.

没有这样的方法,例如KVO系统不需要对象/类向它注册它们支持KVO的属性。任何键都可能支持KVO,唯一的方法就是从作者的文档中知道。

And of course, there is no guarantee that an @property will support KVO; it's quite possible to write a property that doesn't (and may be necessary sometimes). So, getting a list of a class's @propertys and then assuming they're KVO-compliant would be a dangerous choice in my opinion.

当然,@property不能保证支持KVO;编写一个不需要的属性是很有可能的(有时可能是必需的)。因此,在我看来,得到一个类的@propertys列表,然后假设它们与kvos兼容是一个危险的选择。

#4


0  

You need a getPropertyType function. See this post: Get an object attributes list in Objective-C

您需要一个getPropertyType函数。请参阅本文:获取Objective-C中的对象属性列表

#5


0  

For Swift onlookers, you can get this functionality by utilising the Encodable functionality. I will explain how:

对于快速的旁观者,你可以通过使用可编码的功能来获得这个功能。我将解释如何:

  1. Conform your object to Encodable protocol

    使您的对象符合可编码协议

    class ExampleObj: NSObject, Encodable {
        var prop1: String = ""
        var prop2: String = ""
    }
    
  2. Create extension for Encodable to provide toDictionary functionality

    为Encodable创建扩展以提供字典功能

     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. Call toDictionary on your object instance and access keys property.

    在对象实例和访问键属性上调用toDictionary。

    let exampleObj = ExampleObj()
    exampleObj.toDictionary()?.keys
    
  4. Voila! Access your properties like so:

    瞧!访问您的属性如下:

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

#6


-1  

Environment:Xcode7.2,iOS9.2

环境:Xcode7.2 iOS9.2

I use code snippet below to get property names of a specified class,it works fine:

我使用下面的代码片段获取指定类的属性名,它工作得很好:

import "objc/runtime.h"

unsigned int outCount, i;

objc_property_t *properties = class_copyPropertyList([SNBankBean class], &outCount);
for(i = 0; i < outCount; i++) {
    objc_property_t property = properties[i];
    const char *propName = property_getName(property);
    if(propName) {
        NSString *propertyName = [NSString stringWithUTF8String:propName];
        NSLog(@"the property name is %@",propertyName);
        if ([propertyName isEqualToString:bank_name]) {
            self.isBankExisted=YES;
        }
    }
}
free(properties);