2008-12-02 19 views
6

Tôi đánh giá cao một số phản hồi về một cách tiếp cận cụ thể mà tôi đang nghĩ đến việc sử dụng. Kịch bản dưới đây.KVC không phân biệt chữ hoa chữ thường trong ca cao?

Tôi có một đối tượng (cho phép gọi nó là MObject) có một số thuộc tính, như toạ độ x, y, chiều cao và chiều rộng. Các thuộc tính được đặt tên theo hướng dẫn của KVC (MObject.x; MObject.height, v.v.). Nhiệm vụ tiếp theo của tôi là đọc một tệp XML mô tả MObject này. Thật không may, các phần tử XML được đặt tên khác nhau - X và Y, Chiều cao và Chiều rộng (lưu ý cách viết hoa).

Lý tưởng nhất, các phần tử XML sẽ khớp với các thuộc tính của MObject. Trong trường hợp này, tôi có thể sử dụng KVC và tránh toàn bộ mã nguồn:

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

Một cách tiếp cận này là sử dụng các khóa không phân biệt chữ hoa chữ thường. Tôi sẽ bắt đầu từ đâu? Có giải pháp nào khác tốt hơn không?

Đề xuất được đánh giá rất nhiều.

Trả lời

3

Đừng ghi đè -[NSObject valueForKey:]-[NSObject setValue:forKey:] nếu bạn có thể trợ giúp.

Đặt cược tốt nhất của bạn sẽ là chuyển đổi các khóa bạn nhận được từ tệp XML khi đang di chuyển. Sử dụng một phương pháp riêng để thực hiện chuyển đổi và bạn cũng có thể duy trì bộ nhớ cache của các tên cho các khóa thuộc tính, do đó bạn chỉ cần thực hiện từng chuyển đổi một lần.

- (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

Bạn có thể sử dụng số lowercaseString của NSString để chuyển đổi tên khóa XML thành chữ thường, nếu điều đó có ích.

+0

Giải pháp đơn giản tuyệt vời. Làm tốt! –

+0

Điều này sẽ hiệu quả, tôi đoán vấn đề duy nhất là quy ước đặt tên. – EightyEight

1

Ghi đè -valueForKey:-setValue:forKey:.

Bạn có lẽ chỉ nên chấp nhận các khóa (tên phần tử/thuộc tính) mà bạn nhận ra và gọi tới super cho các khóa khác.

3

Override -valueForUndefinedKey:-setValue:forUndefinedKey:

Nếu bạn tìm thấy một chìa khóa với một hoa khác sử dụng nó, nếu không gọi lên đến super.

1

Vì vậy, tôi đã thực hiện đề xuất của Chris Hanson và đây là những gì tôi đã kết thúc. Tôi đặt cái này vào lớp Utils của tôi. Nó giữ một từ điển cho mỗi lớp mà chúng tôi tra cứu. Nó có thể có thể sử dụng một chút refactoring nhưng nó đã làm việc rất tốt cho tôi cho đến nay.

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

Ngoài ra, đừng quên #import

Các vấn đề liên quan