2008-12-02 50 views
6

我很感激我對某種特定方法的反饋。情景如下。Cocoa中不區分大小寫的KVC?

我有一個對象(讓我們稱之爲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]. 
} 

的一種方式。我從哪裏開始?還有其他更好的解決方案嗎?

非常感謝的建議。

回答

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]]. 
    } 
} 
3

如果有幫助,可以使用NSString的lowercaseString將XML密鑰名稱轉換爲小寫。

+0

極其簡單的解決方案。做得好! – 2008-12-03 00:43:41

+0

這將工作,我想唯一的問題是命名約定。 – EightyEight 2008-12-03 00:48:52

1

覆蓋-valueForKey:-setValue:forKey:

您應該只接受您識別的密鑰(元素/屬性名稱),併爲其他密鑰調用super

3

覆蓋-valueForUndefinedKey:-setValue:forUndefinedKey:

如果你找到一個不同的資本使用的關鍵,否則打電話給super

1

因此,我實施了克里斯漢森的建議,這是我最終的結果。我把它放在我的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; 
}