我有一个包含 的项目的数组NSDictionary
,我想将这些项目转换为其他对象,我的第一个想法是valueForKey:
,所以我为 添加了一个类别方法toMyObject
,NSDictionary
并调用:
[array valueForKey:@"toMyObject"]
但它并没有按预期工作,它只是返回NSNull
s 的数组。
如果我不想枚举数组,有什么想法可以解决这个问题?
我有一个包含 的项目的数组NSDictionary
,我想将这些项目转换为其他对象,我的第一个想法是valueForKey:
,所以我为 添加了一个类别方法toMyObject
,NSDictionary
并调用:
[array valueForKey:@"toMyObject"]
但它并没有按预期工作,它只是返回NSNull
s 的数组。
如果我不想枚举数组,有什么想法可以解决这个问题?
回答我自己。of 字典覆盖默认行为,valueForKey:
如果字典没有键,它将返回 nil 并且不会NSObject
像 Apple 文档中所说的那样调用访问器方法:
如果 key 不以“@”开头,则调用 objectForKey:。如果键确实以“@”开头,则去掉“@”并使用键的其余部分调用 [super valueForKey:]。
由于NSDictionary
是集群类,因此不建议子类化来覆盖行为。相反,我使用这样的瑞士方法:
@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"
.
另一种无需混杂的实现:
@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