Objective c 如何从NSDictionary继承?

Objective c 如何从NSDictionary继承?,objective-c,Objective C,我有一个名为Settings的对象,它继承自NSMutableDictionary。当我尝试使用初始化此对象时 Settings *settings = [[Settings alloc] initWithContentsOfFile: @"someFile"] 它返回类型为NSCFDictionary的对象。因此,它无法识别我的其他方法。例如,当我调用选择器“save”时,它将对象: [NSCFDictionary save]: unrecognized selector sent to i

我有一个名为Settings的对象,它继承自
NSMutableDictionary
。当我尝试使用初始化此对象时

Settings *settings = [[Settings alloc] initWithContentsOfFile: @"someFile"]
它返回类型为
NSCFDictionary
的对象。因此,它无法识别我的其他方法。例如,当我调用选择器“save”时,它将对象:

[NSCFDictionary save]: unrecognized selector sent to instance 0x524bc0
当然,当我使用花园品种时,它是可以的

Settings *settings = [[Settings alloc] init]
我试图再次将其转换为设置,但没有成功。这似乎真的很简单-我错过了什么


谢谢

NSDictionary是一个类群集。这意味着从其init方法返回的值严格来说不是NSDictionary,而是实现实际功能的子类。在几乎所有情况下,最好给类一个NSDictionary作为实例变量,或者简单地在NSDictionary上定义一个类别。

Chuck对NSDictionary(以及Dave对NSArray/Set/String的扩展)和类集群的看法是正确的。很可能,
-[NSDictionary initWithContentsOfFile:
调用的初始值设定项与
-init
调用的初始值设定项不同,这就是为什么它会将分配的
设置
实例交换给NSMutableDictionary的另一个子类。(从文件读取时的初始化操作可能会选择NSDictionary的特定已知子类,该子类在从文件加载时表现良好,等等。)

我将响应Chuck的指导,在NSDictionary中使用组合或类别几乎总是比使用继承更好。你很有可能以一种更简单的方式完成你正在做的关于类别的工作,并在这个过程中暴露出更少的潜在错误。在决定子类之前请考虑自己的警告。

也就是说,NSDictionary和NSMutableDictionary都是为了支持子类化而设计的,在极少数情况下,这样做是正确的。在尝试之前,仔细考虑一下。如果您认为它是您设计的正确选择,以下是一些需要了解并根据需要执行的关键点:

  • 从中重写以下基元方法:
    • -计数
    • -objectForKey:
    • -keyEnumerator
    • -initWithObjects:forKeys:count
      :(指定初始值设定项)
  • 从中重写以下基元方法:
    • -setObject:forKey:
    • -removeObjectForKey:
  • 如果您支持,请注意
    classforkeydarchiver
    replacementObjectforkeydarchiver:
    (这两个实例方法都来自NSObject)——它们可以完全改变类的响应方式,并且您经常会无意中从NS(可变)字典继承一些奇怪的行为。(您可以通过设置断点来验证它们是否是罪魁祸首,或者实现它们以调用super并在您自己的代码中破坏它们。)
  • 我已经在自己的NSMutableDictionary子类中实现了其中的一些要点。您可以使用这些代码,但可能会对您有所帮助。其中一个对我特别有帮助的方法(可能是解决您问题的方法)是重载指定的初始值设定项,该初始值设定项目前没有文档记录(Radar#7046209)

    需要记住的是,尽管这些项目符号涵盖了最常见的用途,但总有一些边缘情况和不太常见的功能需要说明。例如,
    -isEqual:
    -hash
    用于测试相等性,等等。

    从,这就是我所做的,以使NSDictionary的子类工作。我只是声明了一个NSDictionary作为类的实例变量,并添加了更多必需的方法。我不知道该怎么称呼他们


    我在这里发布了我的代码示例。

    如果你真的阅读了NSDictionary的规范(我知道这是一个草率的行为),你会发现一个名为“子类注释”的部分。您将在其中阅读:

    如果您确实需要为NSDictionary创建子类,则需要考虑 由类集群表示的,因此有几个 方法概念上基于的基本方法:

    initWithObjects:forKeys:
    
    count
    
    objectForKey:
    
    keyEnumerator
    
    在子类中,必须重写所有这些方法


    这个问题很老了,因为大多数答案都已经发布了,苹果公司已经推出了,它允许您让自己的类更像
    NSMutableArray
    NSMutableDictionary
    。这比上面讨论的备选方案更简单

    至少,您必须覆盖这些方法:

    //Array-style
    - (id)objectAtIndexedSubscript:(NSUInteger)idx;
    - (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx;
    
    //Dictionary-style
    - (id)objectForKeyedSubscript:(id <NSCopying>)key;
    - (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key;
    
    //数组样式
    -(id)objectAtIndexedSubscript:(NSUInteger)idx;
    -(void)setObject:(id)obj atIndexedSubscript:(nsuiger)idx;
    //字典风格
    -(id)objectforkeydsubscript:(id)键;
    -(void)setObject:(id)obj forkeydsubscript:(id)键;
    

    这里有一个关于如何做到这一点的好方法。

    像这样的其他“类”是(最显著的)NSString、NSArray和NSSet。我偶尔会遇到引用“NSBigMutableString”的日志语句,在我了解类集群之前,它一直让我感到困惑我同意这一点。最好是使用has-a关系,而不是is-a关系。(更喜欢组合而不是子类化)。您可以通过重写
    -setValue:forKey:
    -valueForKey:
    等,使您的类像字典一样运行。当我阅读第一句话时,我立即想到,也许可以使用NSUserDefaults来代替创建设置类?当然,我不知道NSUserDefaults是否适合您的需要,但它是为存储设置而设计的,因此可能不需要构建自己的设置。想一想,谢谢。这听起来好像能满足我的要求。我存储的不是一个“默认”值,但这可能会很好。谢谢——你们已经足够让我害怕对NSDictionary进行分类了,至少在我变得更有经验之前是这样。所以我将使用NSUserDefaults,或者使用合成模式。这与苹果公司推荐的类似——一个复合对象:@mahbou