NSDictionary: method only defined for abstract cla

2019-02-05 18:03发布

My app crashed after I called addImageToQueue. I added initWithObjects: forKeys: count: but it doesn't helped me.

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

my code

- (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

3条回答
狗以群分
2楼-- · 2019-02-05 18:34

From https://stackoverflow.com/a/1191351/467588, this is what I did to make a subclass of NSDictionary works. I just declare an NSDictionary as an instance variable of my class and add some more required methods. It's called "Composite Object" - thanks @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
查看更多
老娘就宠你
3楼-- · 2019-02-05 18:42

Are you subclassing NSDictionary? That's not a common thing to do in Cocoa-land, which might explain why you're not seeing the results you expect.

NSDictionary is a class cluster. That means that you never actually work with an instance of NSDictionary, but rather with one of its private subclasses. See Apple's description of a class cluster here. From that doc:

You create and interact with instances of the cluster just as you would any other class. Behind the scenes, though, when you create an instance of the public class, the class returns an object of the appropriate subclass based on the creation method that you invoke. (You don’t, and can’t, choose the actual class of the instance.)

What your error message is telling you is that if you want to subclass NSDictionary, you have to implement your own backend storage for it (for example by writing a hash table in C). It's not just asking you to declare that method, it's asking you to write it from scratch, handling the storage yourself. That's because subclassing a class cluster directly like that is the same as saying you want to provide a new implementation for how dictionaries work. As I'm sure you can tell, that's a significant task.

Assuming you definitely want to subclass NSDictionary, your best bet is to write your subclass to contain a normal NSMutableDictionary as a property, and use that to handle your storage. This tutorial shows you one way to do that. That's not actually that hard, you just need to pass the required methods through to your dictionary property.

You could also try using associative references, which "simulate the addition of object instance variables to an existing class". That way you could associate an NSNumber with your existing dictionary to represent the tag, and no subclassing is needed.

Of course, you could also just have tag as a key in the dictionary, and store the value inside it like any other dictionary key.

查看更多
祖国的老花朵
4楼-- · 2019-02-05 18:58

I just did a little trick.
I'm not sure that its the best solution (or even it is good to do it).

@interface MyDictionary : NSDictionary

@end  

@implementation MyDictionary

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

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

    return self;
}

@end

This worked fine for me.

查看更多
登录 后发表回答