¿Cómo puedo encontrar todas las claves de propiedad de un objeto Objective-C compatible con KVC?


¿Existe un método que devuelva todas las claves de un objeto conforme al protocolo NSKeyValueCoding?

Algo parecido a [object getPropertyKeys] que devolvería un NSArray de objetos NSString. Funcionaría para cualquier objeto compatible con KVC. ¿Existe tal método? No he encontrado nada en la búsqueda de los documentos de Apple hasta ahora.

Gracias, G.

Author: Quinn Taylor, 2009-04-23

6 answers

#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);
 33
Author: oxigen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-08 18:06:33

Use class_getPropertyList. Eso le dirá todo el @properties del objeto.

No necesariamente listará todas las propiedades compatibles con KVC, porque cualquier método que no toma argumentos y devuelve un valor es un getter válido compatible con KVC. No hay una forma 100% confiable para que el tiempo de ejecución sepa cuáles se comportan como propiedades (por ejemplo, -[NSString length]) y cuáles se comportan como comandos (por ejemplo, -[NSFileHandle readDataToEndOfFile]).

Debe declarar sus propiedades compatibles con KVC como @properties de todos modos, por lo que esto no debería ser un gran problema.

 3
Author: Peter Hosey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-23 09:23:37

No existe tal método ya que el sistema KVO no requiere que los objetos/clases registren con él qué propiedades soportan KVO. Cualquier clave podría soportar KVO, la única forma de saberlo es a partir de la documentación del autor.

Y, por supuesto, no hay ninguna garantía de que un @property apoyará KVO; es muy posible escribir una propiedad que no (y puede ser necesario a veces). Por lo tanto, obtener una lista de @propertys de una clase y luego asumir que son compatibles con KVO sería sería una elección peligrosa en mi opinión.

 1
Author: Mike Abdullah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-09 23:14:15

Necesita una función getPropertyType. Ver este post: Obtener una lista de atributos de objeto en Objective-C

 0
Author: Chatchavan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:09:14

Para los espectadores de Swift, puede obtener esta funcionalidad utilizando la funcionalidad Encodable. Voy a explicar cómo:

  1. Conforma tu objeto al protocolo Encodable

    class ExampleObj: NSObject, Encodable {
        var prop1: String = ""
        var prop2: String = ""
    }
    
  2. Crear extensión para Encodable para proporcionar toDictionary funcionalidad

     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. Llame a toDictionary en su instancia de objeto y acceda a la propiedad keys.

    let exampleObj = ExampleObj()
    exampleObj.toDictionary()?.keys
    
  4. Voila! Acceda a sus propiedades de la siguiente manera:

    for k in exampleObj!.keys {
        print(k)
    }
    // Prints "prop1"
    // Prints "prop2"
    
 0
Author: Harry Bloom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-21 13:59:58

Entorno: Xcode7.2, iOS9. 2

Utilizo el fragmento de código a continuación para obtener los nombres de propiedad de una clase especificada, funciona bien:

Importar "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
Author: iengchen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-18 08:15:13