代码之家  ›  专栏  ›  技术社区  ›  EightyEight

Cocoa中不区分大小写的KVC?[闭门]

  •  6
  • EightyEight  · 技术社区  · 17 年前

    理想情况下,XML元素将与MObject的属性匹配。在这种情况下,我可以使用KVC并避免一系列代码:

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

    一种方法是使用不区分大小写的键。我从哪里开始呢?还有其他更好的解决方案吗?

    5 回复  |  直到 17 年前
        1
  •  3
  •   Chris Hanson    17 年前

    不要超越 -[NSObject valueForKey:] -[NSObject setValue:forKey:] 如果你能帮忙的话。

    最好的办法是动态转换从XML文件中获取的密钥。使用单独的方法进行转换,还可以维护名称到属性键的缓存,因此每次转换只需执行一次。

    - (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]].
        }
    }
    
        2
  •  3
  •   Marc Charbonneau    17 年前

    您可以使用NSString的 lowercaseString

        3
  •  3
  •   Ashley Clark    17 年前

    -valueForUndefinedKey: -setValue:forUndefinedKey:

    如果您发现一个键的大小写不同,请使用它,否则请调用 super .

        4
  •  1
  •   Peter Hosey    17 年前

    推翻 -valueForKey: -setValue:forKey: .

    super

        5
  •  1
  •   Cody C    13 年前

    所以我实施了克里斯·汉森的建议,以下是我的结论。我把这个放在我的实用课上。它为我们查找的每个类保留一个字典。它可能需要一些重构,但到目前为止对我来说效果非常好。

    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;
    }