6

对于我正在考虑使用的特定方法,我将不胜感激。场景如下。

我有一个对象(我们称之为 MObject),它有许多属性,比如 x 和 y 坐标、高度和宽度。这些属性是根据 KVC 指南命名的(MObject.x;MObject.height 等)。我的下一个任务是读入描述这个 MObject 的 XML 文件。不幸的是,XML 元素的名称不同——X 和 Y、高度和宽度(注意大写)。

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

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

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

建议非常感谢。

4

5 回答 5

3

如果有帮助,您可以使用 NSStringlowercaseString将 XML 键名转换为小写。

于 2008-12-03T00:24:43.527 回答
3

覆盖-valueForUndefinedKey:-setValue:forUndefinedKey:

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

于 2008-12-03T03:21:52.673 回答
3

不要覆盖-[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]].
    }
}
于 2008-12-03T03:36:21.347 回答
1

覆盖-valueForKey:-setValue:forKey:

您可能应该只接受您识别的键(元素/属性名称),并调用super其他键。

于 2008-12-03T01:40:52.860 回答
1

所以我实施了 Chris Hanson 的建议,这就是我最终的结果。我把它放在我的 Utils 课上。它为我们查找的每个类保留一个字典。它可能需要进行一些重构,但到目前为止它对我来说效果很好。

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;
}
于 2012-09-14T17:46:48.620 回答