2

私が取り組んでいるプログラムでは、charのC配列を使用しています(これは潜在的に非常に大きな配列であるため、NSArrayを使用したくありません)。それぞれが特定のステータスに対応する値を格納しています。

各ステータスに関する情報を保存できるように、NSDictionaryを使用しています。各キーは、可能なステータス値に対応しています。各キーの値は、ステータス値に対応するために必要な情報を含むサブディクショナリです。

現在、NSDictionaryから情報を抽出したいときはいつでも、次のことを行っています。

for(i=0; i<arrayLen; i++) {

NSString *lookupKey1 = [[NSString alloc]initWithFormat:@"%i", array[i]];
int stateInfo1 = [[[statesDict objectForKey:lookupKey1] 
                                objectForKey:@"infoKey1"] intValue];
[lookupKey1 release];


NSString *lookupKey2 = [[NSString alloc]initWithFormat:@"%i", array[i]];
int stateInfo2 = [[[statesDict objectForKey:lookupKey2] 
                                objectForKey:@"infoKey2"] intValue];
[lookupKey2 release];


// Now do something with the values just obtained...

}

これは問題なく機能しますが、これを実行する必要がないのは、キーを検索するためだけにNSStringを割り当てる必要があることです。不必要な操作をしているような気がします。私は大きな配列を反復処理しているので、これは私にとって特に懸念事項です。絶対に必要な場合を除いて、この方法で速度を落としたくありません。

私が最初に望んでいたように、単に文字を渡そうとすると、次のことができます。

char stateInfo = [[[statesDict objectForKey:array[i]] 
                                objectForKey:@"infoKey"] charValue];

コンパイラーは「objectForKeyの引数1を渡す:キャストなしで整数からポインターを作成します」という警告を出し、デバッガーはEXC_BAD_ACCESS例外をスローします。

また、フォーマットされた文字列リテラルを渡してみました。

char stateInfo = [[[statesDict objectForKey:(@"%i", array[i])] 
                                objectForKey:@"infoKey"] charValue];

これにより、まったく同じエラーが発生します。私がやろうとしていることをより効率的に行う方法があるかどうか、または最初のスニペットで説明した方法が、私がやろうとしていることを実行するための「正しい」方法であるかどうかを誰かが知っていますか?

4

3 に答える 3

2

アクセスを簡素化するためにできることは2つあります。

  • NSNumberの代わりにNSStringあなたのキーとして使用してくださいNSDictionary
  • 自動解放されたキーを使用して、release

これにより、コードが少し単純化されます。

int stateInfo2 = [[[statesDict objectForKey:[NSNumber numberWithInt:array[i]]] 
                            objectForKey:@"infoKey2"] intValue];

NSNumberコードの数が比較的少ない場合、現在の実装では割り当てがない可能性が高くなります。このリンクによる[NSNumber numberWithInt:...]と、整数の値が小さい場合は同じオブジェクトが返されます。

編集:プロパティリストは、以外のタイプのキーをサポートしていないためNSString、plistから取得したディクショナリを次のNSNumberようなキーを持つディクショナリに変換する必要があります。

NSDictionary *fromPlist = ... // This is your original dictionary
NSMutableDictionary *target = [NSMutableDictionary dictionary];
[fromPlist enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop){
    [target setObject:obj forKey:[key intValue]];
}];
于 2012-11-13T16:03:45.093 に答える
2

NSDictionary *は、オブジェクトをキーと値としてのみ取得できます。charを渡すと、ポインターにキャストされます。

@dasblinkenlightは良い提案をしますが、フレームワークが共有NSNumberインスタンスを提供することを決定したときは、OSリリース間で異なる可能性があります。

もう1つのオプションは、拡張子が.mmになるようにソースファイルの名前を変更し、c ++ std::mapを使用することです。これはこの種のことを簡単に処理します。

#import <map>

@implementation MyClass {
  std::map<char, int> statesMap;

...

int stateInfo1 = statesMap[i];

そうは言っても、あなたがこれについて不必要に心配しているのではないかと心配しています。

これらのオブジェクトはすべて、パフォーマンスに優れているわけではありません

10,000個の要素を持つ配列でも、一意のオブジェクトキーを使用する場合のメモリオーバーヘッドは約80kになります。いくつかのアイコンに相当します。これらを何百も作成していない限り、メモリの問題が発生する可能性はほとんどありません。パフォーマンスに関しては、仮定ではなく、プロファイリングツールからデータを取得します。ボトルネックは、予想される場所にある可能性は低いです。

于 2012-11-13T16:18:30.867 に答える
1

やってみました

char stateInfo = [[[statesDict objectForKey:[NSString stringWithFormat:@"%i", array[i]] 
                                objectForKey:@"infoKey"] charValue];
于 2012-11-13T16:03:58.383 に答える