2012-02-05 13 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 * capitals = [配列valueForKey:@ "capitalizedString"]; ' – cxa

+0

ここにdoc: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がそうであるようにアクセサメソッドを呼び出してnilを返し、ないだろう、デフォルトの動作を上書き"@"は、objectForKey:を呼び出します。キーに が「@」で始まる場合は、「@」を取り除き、 のキーで[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 
関連する問題