Cocoa中不区分大小写的KVC?
对于我正在考虑使用的特定方法,我希望能得到一些反馈。情况如下 我有一个对象(我们称之为MObject),它有很多属性,比如x和y坐标,高度和宽度。属性是根据KVC指南命名的(MObject.x;MObject.height等)。我的下一个任务是读入描述这个MObject的XML文件。不幸的是,XML元素的名称不同——X和Y、高度和宽度(注意大小写) 理想情况下,XML元素将与MObject的属性匹配。在这种情况下,我可以使用KVC并避免一系列代码:Cocoa中不区分大小写的KVC?,cocoa,key-value-observing,key-value-coding,Cocoa,Key Value Observing,Key Value Coding,对于我正在考虑使用的特定方法,我希望能得到一些反馈。情况如下 我有一个对象(我们称之为MObject),它有很多属性,比如x和y坐标,高度和宽度。属性是根据KVC指南命名的(MObject.x;MObject.height等)。我的下一个任务是读入描述这个MObject的XML文件。不幸的是,XML元素的名称不同——X和Y、高度和宽度(注意大小写) 理想情况下,XML元素将与MObject的属性匹配。在这种情况下,我可以使用KVC并避免一系列代码: for (xmlProperty in xml
for (xmlProperty in xmlElement)
{
[MObject setValue:xmlProperty.value forKey:xmlProperty.name].
}
一种方法是使用不区分大小写的键。我从哪里开始呢?还有其他更好的解决方案吗
非常感谢您的建议。如果有帮助的话,您可以使用NSString的
小写
将XML键名转换为小写。覆盖-valueForKey:
和-setValue:forKey:
您可能应该只接受您识别的键(元素/属性名称),并为其他键调用
super
。覆盖-valueForUndefinedKey:
和-setValue:forUndefinedKey:
如果您发现一个键的大小写不同,请使用它,否则请调用
super
如果您有任何帮助,请不要覆盖-[NSObject valueForKey:][/code>和-[NSObject setValue:forKey:][/code>
最好的办法是动态转换从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]].
}
}
所以我实施了克里斯·汉森的建议,以下是我的结论。我把这个放在我的实用课上。它为我们查找的每个类保留一个字典。它可能需要一些重构,但到目前为止对我来说效果非常好
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;
}
静态NSMutableDictionary*keyCache;
+(NSString*)keyForClass:(Class)klass列:(NSString*)列{
如果(!keyCache){keyCache=[NSMutableDictionary];}
NSString*className=NSStringFromClass(klass);
NSMutableDictionary*tableKeyCache=[keyCache objectForKey:className];
如果(!tableKeyCache){
tableKeyCache=[NSMutableDictionary];
无符号整数方法=0;
方法*methods=class_copyMethodList(klass和numMethods);
NSMutableArray*选择器=[NSMutableArray];
对于(int i=0;i
非常简单的解决方案。做得好!这是可行的,我想唯一的问题是命名约定。另外,别忘了导入