【问题标题】:Objective-C override valueForKey: of NSMutableDictionaryObjective-C 覆盖 valueForKey: 的 NSMutableDictionary
【发布时间】:2011-04-21 15:17:29
【问题描述】:

我需要覆盖 NSMutableDictionary 的 valueForKey: 方法。我想检查一个特定的值,做一些操作并返回它。有什么我应该注意的地方吗?如有错误请指正,例如:

- (id)valueForKey:(NSString*)key {

    id val = [super valueForKey:key];
    if([val isKindOfClass:[NSString class]] && [val isEqualToString:@"<null>"]) {
        return @"No Value";
    }
    else {
        return val;
    }

}

谢谢

【问题讨论】:

标签: objective-c overriding nsmutabledictionary


【解决方案1】:

您可能不想覆盖valueForKey,因为NSDictionaryNSMutableDictionary 是抽象基类,它们背后隐藏着一个类簇。根据他们的文档,在直接子类中,您需要重新实现所有:

  • setObject:forKey:
  • removeObjectForKey:
  • 计数
  • objectForKey:
  • keyEnumerator

实现一个伪装成 NSMutableDictionary 但将它不理解的任何调用转发给实际的 NSMutableDictionary 的替代类更容易。您可以通过forwardingTargetForSelector: 进行操作。

例如

@interface MyFakeDictionary: NSObject
{
    NSMutableDictionary *theRealDictionary;
}

/* reimplement whatever init methods you want to use */

- (id)valueForKey:(id)key;

@end

...

@implementation MyFakeDictionary

- (id)valueForKey:(id)key
{
   id val = [theRealDictionary objectForKey:key];
   /* etc, as you like */
}

- (id)forwardingTargetForSelector:(SEL)aSelector
{
    return theRealDictionary;
}

@end

所以 MyFakeDictionary 和 NSMutableDictionary 之间没有继承关系,但是如果你向 MyFakeDictionary 发送一个它不理解的选择器(就像你替换的任何普通字典消息一样),NSObject 的内置逻辑会将它们重定向到成员 theRealDictionary。它是 'has a' 而不是 'is a',具有透明的消息转发,因此可以方便地避开类集群的任何问题。

【讨论】:

  • 当然我需要分配它并在-init & -dealloc 中释放它是吗?听起来最好的解决方案!但我一直在使用@interface ... 来声明类等。@class ... 让编译器给我... error: expected ';' before '{' token ??我错过了什么?
  • 你没有错过任何东西,我的大脑出了问题。 @class 用于声明接口存在但不定义它们,@interface 用于定义它们。您使用@interface 是完全正确的,我在最初的答案中使用@class 是非常错误的,我会立即纠正它。并且:是的,您需要为变量“theRealDictionary”创建一个 NSMutableDictionary 以在 init 中引用,然后在 dealloc 中释放它。你实际上需要重新实现你想要的 inits,所以你想要'initWithObjectsAndKeys:' 你必须创建字典,然后将对象推入其中。
  • 谢谢@Tommy,如果大厅的事情对我有用,我会回来的。
  • xm,我将不得不花一些时间在这个问题上,我会收到很多警告、错误,例如 ...does not implement methodSignatureForSelector: 等问题。不过似乎仍然是正确的解决方案......也许我会尝试使用 NSValueTransformer 女巫的解决方案,这对我来说可能是最好的。谢谢...
  • 对不起;临时编码的另一个错误:你的对象应该继承自 NSObject。我会更正我的答案。
【解决方案2】:

子类化 NSMutableDictionary 时一定要注意:

来自 Apple 文档:

Methods to Override

In a subclass, you must override both
of its primitive methods:

setObject:forKey: 
removeObjectForKey:
You must also override the primitive methods of the NSDictionary class.

【讨论】:

    【解决方案3】:

    获取您的代码并将其包装在以下内容中:

    @implementation NSMutableDictionary(myValueForKey)
    
    <your code here>
    
    @end
    

    这是 NSMutableDictionary 上的一个类别。类别使添加或扩充标准方法变得容易,而无需子类化。

    不过,一个建议是使用不同的方法名称,因为您不想调用[super valueForKey:...],而是想调用[self valueForKey:...]。因此,为您的方法使用不同的方法名称将使您的方法与标准方法区分开来。

    【讨论】:

    • 我使用 IB 绑定,所以我希望 valueForKey: 被“覆盖”,也可以使用绑定。那么我应该为默认实现调用 [super ...] 还是在 category 的情况下调用 [self ...] ?谢谢
    • 使用类别,您正在扩展一个类,因此当调用类别方法时,self 指的是正在调用该方法的对象(接收者)。因此,如果您创建一个类别方法,例如myValueForKey:,那么该方法中的self 指的是您调用myValueForKey: 的对象,然后您可以调用[self valueForKey:...] 来获取原始类的valueForKey: 方法。这与子类化类和覆盖基类方法不同。在这种情况下,您可以通过调用 super 上的原始方法来访问基类功能。
    猜你喜欢
    • 2011-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多