2012-02-05 2 views
2

나는 NSDictionary의 항목을 포함하는 배열, 나는 다른 개체에 항목을 변환 할 가지고, 내 첫번째 생각은 valueForKey:, 그래서, NSDictionary에 대한 분류 방법 toMyObject 추가 그러나 예상대로 작동하지 않습니다문제 : 그 항목이있는 NSDictionary 때

[array valueForKey:@"toMyObject"]

그냥 NSNull의 배열을 반환 :과에 문의하십시오.

배열을 열거하지 않으려는 경우이 문제를 해결할 수있는 아이디어가 있습니까?

+2

안녕 디트리히,'NSArray'의'valueForKey :'각 항목에 대해 호출됩니다 및 항목의'valueForKey의 결과를 포함하는 새 배열을 반환합니다' . Xcode를 열고 다음을 시도 할 수 있습니다 : NSArray array = [NSArray arrayWithObjects : @ "foo", @ "bar", @ "baz", nil]; NSArray * 대문자 = [배열 valueForKey : @ "capitalizedString"]; ' – cxa

+0

및 여기에 문서 : https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray .html # // apple_ref/doc/uid/20000137-BBCIBCDJ – vikingosegundo

+0

흠, 재단 변경 사항에 신경 쓰지 않은 것 같습니다. –

답변

0

나에게 답변. 사전의 valueForKey:는 기본 동작을 덮어 사전은 키가없는 경우 애플 문서가 말한대로, 그것은 수행 전무를 반환하고 NSObject으로 접근 메소드를 호출하지 않습니다

키로 시작하지 않는 경우 "@", objectForKey :를 호출합니다. key가 이 "@"로 시작하면 "@"을 제거하고 [super valueForKey :]를 키와 함께 호출합니다.

NSDictionary은 클러스터 클래스이므로 하위 클래스를 사용하여 동작을 덮어 쓰지 않는 것이 좋습니다. 있는 NSArray가 valueForKey:@"toMyObject"를 호출하는

@implementation NSDictionary (MyAddition) 

static void swizzle(Class c, SEL orig, SEL new) 
{ 
    Method origMethod = class_getInstanceMethod(c, orig); 
    Method newMethod = class_getInstanceMethod(c, new); 
    if(class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) 
    class_replaceMethod(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod)); 
    else 
    method_exchangeImplementations(origMethod, newMethod); 
} 

+ (void)initialize 
{ 
    if (self == [NSDictionary class]){ 
    swizzle([NSDictionary class], 
      @selector(valueForKey:), 
      @selector(myValueForKey:)); 
    } 
} 

- (id)toMyObject 
{ 
    return toMyObject; 
} 

... 

- (id)myValueForKey:(NSString *)key 
{ 
    // for collection operators 
    if ([key compare:@"@" options:0 range:NSMakeRange(0, 1)] == NSOrderedSame) 
    return [super valueForKey:key]; 

    if ([key isEqualToString:@"toMyObject"]) 
    return [self toMyObject]; 

    return [self myValueForKey:key]; 
} 

가 지금은 안전 대신이 같은 스위스 방법을 사용합니다.

+3

와우. 이것은 여러 가지 방법으로 깨졌습니다. –

+0

1. 왜 클래스 클러스터에서 서브 클래 싱하는 것보다 스위 즐링이 안전하다고 생각합니까? (그렇지 않습니다.) –

+0

2.'myValueForKey :'는 키가 "toMyObject"가 아닐 때 영원히 재귀 적으로 호출합니다. –

0

스위 즐링없는 또 하나의 구현 :

@implementation NSObject (MLWValueForKey) 

- (id)mlw_valueForKey:(NSString *)key { 
    if ([key hasPrefix:@"@"]) { 
     return [self valueForKey:key]; 
    } 
    NSAssert(![key containsString:@":"], @"Key should be selector without arguments"); 
#pragma clang diagnostic push 
#pragma clang diagnostic ignored "-Warc-performSelector-leaks" 
    return [self performSelector:NSSelectorFromString(key)]; 
#pragma clang diagnostic pop 
} 

@end 

@implementation NSArray (MLWValueForKey) 

- (id)mlw_valueForKey:(NSString *)key { 
    if ([key hasPrefix:@"@"]) { 
     return [self valueForKey:key]; 
    } 
    NSMutableArray *array = [NSMutableArray arrayWithCapacity:self.count]; 
    for (id object in self) { 
     [array addObject:[object mlw_valueForKey:key]]; 
    } 
    return array; 
} 

@end