22

在我调用 addImageToQueue 后,我的应用程序崩溃了。我添加了 initWithObjects: forKeys: count: 但它对我没有帮助。

Terminating app due to uncaught exception 'NSInvalidArgumentException', 
reason: '*** -[NSDictionary initWithObjects:forKeys:count:]: 
method only defined for abstract class.  
Define -[DictionaryWithTag initWithObjects:forKeys:count:]!'

我的代码

- (void)addImageToQueue:(NSDictionary *)dict
{
 DictionaryWithTag *dictTag = [DictionaryWithTag dictionaryWithDictionary:dict];
}

@interface DictionaryWithTag : NSDictionary
@property (nonatomic, assign) int tag;

- (id)initWithObjects:(id *)objects forKeys:(id *)keys count:(NSUInteger)count;

@end

@implementation DictionaryWithTag

@synthesize tag;

- (id)initWithObjects:(id *)objects forKeys:(id *)keys count:(NSUInteger)count
{
 return [super initWithObjects:objects forKeys:keys count:count];
}
@end
4

3 回答 3

43

你在继承 NSDictionary 吗?这在 Cocoa-land 并不常见,这可以解释为什么您没有看到预期的结果。

NSDictionary 是一个类簇。这意味着您实际上永远不会使用 NSDictionary 的实例,而是使用它的私有子类之一。在此处查看 Apple 对类集群的描述。从那个文档:

您可以像创建任何其他类一样创建集群实例并与之交互。但是,在幕后,当您创建公共类的实例时,该类会根据您调用的创建方法返回相应子类的对象。(您没有也不能选择实例的实际类。)

你的错误信息告诉你的是,如果你想继承 NSDictionary,你必须为它实现你自己的后端存储(例如通过在 C 中编写一个哈希表)。它不仅要求您声明该方法,还要求您从头开始编写它,自己处理存储。这是因为像这样直接对类集群进行子类化与说您想为字典的工作方式提供新的实现是一样的。我相信你可以说,这是一项重大的任务。

假设你肯定想要继承 NSDictionary,你最好的办法是编写你的子类来包含一个普通的 NSMutableDictionary 作为属性,并用它来处理你的存储。本教程向您展示了一种方法。这实际上并不难,您只需将所需的方法传递给您的字典属性。

您也可以尝试使用关联引用,它“模拟将对象实例变量添加到现有类”。这样,您可以将 NSNumber 与现有字典关联以表示标记,并且不需要子类化。

当然,您也可以将tag其作为字典中的键,并将值存储在其中,就像任何其他字典键一样。

于 2012-05-29T13:14:53.133 回答
6

https://stackoverflow.com/a/1191351/467588,这就是我为制作 NSDictionary 作品的子类所做的工作。我只是将一个 NSDictionary 声明为我的类的实例变量并添加一些更多必需的方法。它被称为“复合对象” - 感谢@mahboudz。

@interface MyCustomNSDictionary : NSDictionary {
    NSDictionary *_dict;
}
@end

@implementation MyCustomNSDictionary
- (id)initWithObjects:(const id [])objects forKeys:(const id [])keys count:(NSUInteger)cnt {
    _dict = [NSDictionary dictionaryWithObjects:objects forKeys:keys count:cnt];
    return self;
}
- (NSUInteger)count {
    return [_dict count];
}
- (id)objectForKey:(id)aKey {
    return [_dict objectForKey:aKey];
}
- (NSEnumerator *)keyEnumerator {
    return [_dict keyEnumerator];
}
@end
于 2012-06-12T09:11:24.570 回答
2

我只是做了一个小把戏。
我不确定它是否是最好的解决方案(或者即使这样做也很好)。

@interface MyDictionary : NSDictionary

@end  

@implementation MyDictionary

+ (id) allocMyDictionary
{
    return [[self alloc] init];
}

- (id) init
{
    self = (MyDictionary *)[[NSDictionary alloc] init];

    return self;
}

@end

这对我来说很好。

于 2014-01-04T17:04:41.783 回答