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をサブクラス化していますか?これはココアランドでは一般的ではありません。これは、期待する結果が得られない理由を説明している可能性があります。

NSDictionaryはクラスクラスターです。つまり、実際にNSDictionaryのインスタンスを操作するのではなく、そのプライベートサブクラスの1つを操作することになります。ここで、クラスクラスターに関するAppleの説明を参照してください。そのドキュメントから:

他のクラスと同じように、クラスターのインスタンスを作成して操作します。ただし、舞台裏では、パブリッククラスのインスタンスを作成すると、呼び出した作成メソッドに基づいて、クラスが適切なサブクラスのオブジェクトを返します。(インスタンスの実際のクラスを選択することはできません。また、選択することもできません。)

エラーメッセージが示しているのは、NSDictionaryをサブクラス化する場合は、独自のバックエンドストレージを実装する必要があるということです(たとえば、Cでハッシュテーブルを作成することによって)。そのメソッドを宣言するように要求するだけでなく、ストレージを自分で処理して、最初から作成するように要求します。これは、クラスクラスターをそのように直接サブクラス化することは、辞書がどのように機能するかについて新しい実装を提供したいと言うことと同じであるためです。お分かりのように、それは重要な仕事です。

NSDictionaryを確実にサブクラス化する場合、最善の策は、通常のNSMutableDictionaryをプロパティとして含むようにサブクラスを作成し、それを使用してストレージを処理することです。このチュートリアルでは、そのための1つの方法を示します。これは実際にはそれほど難しいことではありません。必要なメソッドをディクショナリプロパティに渡す必要があります。

「既存のクラスへのオブジェクトインスタンス変数の追加をシミュレートする」連想参照を使用することもできます。そうすれば、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 に答える