objective c objetos ¿Cómo encuentro todas las claves de propiedad de un objeto Objective-C compatible con KVC?



propiedades de un objeto (5)

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

¿Hay algún método que devuelva todas las claves de un objeto que cumpla con el protocolo NSKeyValueCoding?

Algo a lo largo de las líneas de [object getPropertyKeys] que devolvería una 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.


Answer #1

No existe un método como el sistema KVO que no requiere que los objetos / clases registren para qué propiedades son compatibles con KVO. Cualquier clave podría ser compatible con KVO, la única forma de saber es a partir de la documentación del autor.

Y, por supuesto, no hay garantía de que una @property sea ​​compatible con KVO; es muy posible escribir una propiedad que no lo hace (y puede ser necesario a veces). Por lo tanto, obtener una lista de las @property s de una clase y luego asumir que son compatibles con KVO sería una opción peligrosa en mi opinión.


Answer #2

Utilice class_getPropertyList . Eso te dirá todas las @properties del objeto.

No necesariamente listará todas las propiedades compatibles con KVC, porque cualquier método que no tome argumentos y devuelva un valor es un captador válido que cumple 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] ).

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


Answer #3

Para los Encodable Swift, puede obtener esta funcionalidad utilizando la funcionalidad Encodable . Explicaré cómo:

  1. Conforme su objeto al protocolo Encodable

    class ExampleObj: NSObject, Encodable {
        var prop1: String = ""
        var prop2: String = ""
    }
    
  2. Crear una extensión para Encodable para proporcionar funcionalidad de 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. Llame a toDictionary en su instancia de objeto y acceda a la propiedad de keys .

    let exampleObj = ExampleObj()
    exampleObj.toDictionary()?.keys
    
  4. Voila! Acceda a sus propiedades como tal:

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

Answer #4

Entorno: Xcode7.2, iOS9.2

Uso el siguiente fragmento de código para obtener los nombres de propiedad de una clase específica, 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);




key-value-observing