2

在我正在处理的程序中,我使用了一个 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

NSDictionary* 只能将对象作为键和值。当你将它传递给一个字符时,它会将它转换为一个指针。

@dasblinkenlight 提出了一个很好的建议,尽管我猜您在框架决定为您提供共享 NSNumber 实例时会稍有摆布,这可能因操作系统版本而异。

另一种选择是重命名您的源文件,以便扩展名为 .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 回答
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 回答
1

你有没有尝试过

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