코코아에서 사례에 민감한 KVC? [닫은
-
22-07-2019 - |
문제
내가 생각하고자하는 특정 접근법에 대한 피드백에 감사드립니다. 시나리오는 다음과 같습니다.
X 및 Y 좌표, 높이 및 너비와 같은 여러 속성이있는 객체 (mobject라고 부르겠습니다)가 있습니다. 속성은 KVC 가이드 라인 (mobject.x; mobject.height 등)에 따라 명명되었습니다. 다음 과제는이 mobject를 설명하는 XML 파일로 읽는 것입니다. 불행히도 XML 요소의 이름은 x와 y, 높이 및 너비 (대문자에 유의)입니다.
이상적으로 XML 요소는 Mobject의 속성과 일치합니다. 이 경우 KVC를 사용하고 전체 코드를 피할 수 있습니다.
for (xmlProperty in xmlElement)
{
[MObject setValue:xmlProperty.value forKey:xmlProperty.name].
}
이에 접근하는 한 가지 방법은 케이스에 민감한 키를 사용하는 것입니다. 어디서부터 시작할까요? 다른 더 나은 솔루션이 있습니까?
제안은 대단히 감사했습니다.
해결책
무시하지 마십시오 -[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]].
}
}
다른 팁
NSString을 사용할 수 있습니다 lowercaseString
XML 키 이름을 소문자로 변환하려면 도움이되면 도움이됩니다.
우세하다 -valueForUndefinedKey:
그리고 -setValue:forUndefinedKey:
대문자가 다른 키를 찾으면 사용하십시오. 그렇지 않으면 전화하십시오. super
.
우세하다 -valueForKey:
그리고 -setValue:forKey:
.
당신은 아마 당신이 인식하는 키 (요소/속성 이름) 만 허용해야하며 super
다른 키를 위해.
그래서 저는 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;
}