2

の項目を含む配列がありますNSDictionary。項目を他のオブジェクトに変換したいのですが、最初に考えたのは です。そのため、のカテゴリ メソッドをvalueForKey:追加し、次のように呼び出します。toMyObjectNSDictionary

[array valueForKey:@"toMyObject"]

しかし、それは期待どおりには機能せず、NSNulls の配列を返すだけです。

配列を列挙したくない場合、この問題を解決するためのアイデアはありますか?

4

2 に答える 2

1

自分に答えてください。of ディクショナリはデフォルトの動作を上書きします。valueForKey:ディクショナリにキーがない場合、nil が返さNSObjectれ、Apple のドキュメントにあるようにアクセサ メソッドは呼び出されません。

キーが「@」で始まらない場合、objectForKey: を呼び出します。キーが「@」で始まる場合、「@」を取り除き、残りのキーで [super valueForKey:] を呼び出します。

はクラスター クラスであるためNSDictionary、サブクラス化して動作を上書きすることはお勧めしません。代わりに、次のようにメソッド swiss を使用します。

@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];
}

これで、NSArray が安全に を呼び出すことができますvalueForKey:@"toMyObject"

于 2012-02-05T04:07:43.703 に答える
0

スウィズリングなしのもう 1 つの実装:

@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
于 2016-05-31T15:40:48.260 に答える