2008-12-02 14 views
6

Agradecería algunos comentarios sobre un enfoque particular que estoy pensando en usar. El escenario está abajo.KVC insensible a mayúsculas/minúsculas en Cocoa?

Tengo un objeto (vamos a llamarlo MObject) que tiene una serie de propiedades, por ejemplo, coordenadas xey, alto y ancho. Las propiedades se nombran de acuerdo con las directrices de KVC (MObject.x; MObject.height, etc.). Mi próxima tarea es leer en un archivo XML que describa este MObject. Desafortunadamente, los elementos XML tienen un nombre diferente: X e Y, alto y ancho (tenga en cuenta las mayúsculas).

Idealmente, los elementos XML coincidirían con las propiedades de MObject. En este caso, podría usar KVC y evitar todo un golpe de código:

for (xmlProperty in xmlElement) 
{ 
    [MObject setValue:xmlProperty.value forKey:xmlProperty.name]. 
} 

Una forma de abordar este sería hacer uso de las teclas de mayúsculas y minúsculas. ¿Dónde comenzaría con eso? ¿Hay alguna otra mejor solución?

Sugerencias muy apreciadas.

Respuesta

3

No anule -[NSObject valueForKey:] y -[NSObject setValue:forKey:] si puede ayudarlo.

Lo mejor que puede hacer es convertir al instante las claves que obtiene del archivo XML. Utilice un método diferente para realizar la conversión y también puede mantener un caché de nombres para las claves de propiedad, por lo que solo necesita hacer cada conversión una vez.

- (NSString *)keyForName:(NSString *)name { 
    // _nameToKeyCache is an NSMutableDictionary that caches the key 
    // generated for a given name so it's only generated once per name 
    NSString *key = [_nameToKeyCache objectForKey:name]; 
    if (key == nil) { 
     // ...generate key... 
     [_nameToKeyCache setObject:key forKey:name]; 
    } 
    return key; 
} 

- (void)foo:xmlElement { 
    for (xmlProperty in xmlElement) { 
     [myObject setValue:xmlProperty.value forKey:[self keyForName:xmlProperty.name]]. 
    } 
} 
3

Puede usar lowercaseString de NSString para convertir el nombre de la clave XML a minúsculas, si eso ayuda.

+0

Brilliantly simple solution. ¡Bien hecho! –

+0

Esto funcionaría, supongo que el único problema son las convenciones de nomenclatura. – EightyEight

1

Anular -valueForKey: y -setValue:forKey:.

Probablemente solo acepte las claves (nombres de elementos/atributos) que reconoce, y llame al super para obtener otras claves.

3

Anulación -valueForUndefinedKey: y -setValue:forUndefinedKey:

Si encuentra una llave con una capitalización de diferente uso, de lo contrario llamar hasta super.

1

Así que implementé la sugerencia de Chris Hanson y esto es lo que terminé con. Puse esto en mi clase de Utils. Guarda un diccionario para cada clase que buscamos. Probablemente podría usar un poco de refactorización, pero me ha funcionado muy bien hasta ahora.

static NSMutableDictionary *keyCache; 

+ (NSString *)keyForClass:(Class)klass column:(NSString *)column { 
    if (!keyCache) { keyCache = [NSMutableDictionary dictionary]; } 

    NSString *className = NSStringFromClass(klass); 

    NSMutableDictionary *tableKeyCache = [keyCache objectForKey:className]; 

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

     unsigned int numMethods = 0; 
     Method *methods = class_copyMethodList(klass, &numMethods); 
     NSMutableArray * selectors = [NSMutableArray array]; 
     for (int i = 0; i < numMethods; ++i) { 
      SEL selector = method_getName(methods[i]); 
      [selectors addObject:NSStringFromSelector(selector)]; 
     } 
     [tableKeyCache setValue:selectors forKey:@"allSelectors"]; 
     free(methods); 
     [keyCache setValue:tableKeyCache forKey:className]; 
    } 

    NSString *keyToReturn = [tableKeyCache valueForKey:column]; 
    if (!keyToReturn) { 
     for (NSString *columnKey in [tableKeyCache valueForKey:@"allSelectors"]) { 
      if ([column caseInsensitiveCompare:columnKey] == NSOrderedSame) { 
       [tableKeyCache setValue:columnKey forKey:column]; 
       keyToReturn = columnKey; 
       break; 
      } 
     } 
    } 

    if (!keyToReturn) { // Taking a guess here... 
     NSLog(@"Selector not found for %@: %@ ", className, column); 
     keyToReturn = [Utils keyForClass:[klass superclass] column:column]; 
    } 

    return keyToReturn; 
} 
+0

Además, no olvide # import

Cuestiones relacionadas