由于密钥放置在NSDictionary 内的性质,不能保证对密钥进行排序。但这只是一半的答案。继续阅读...
如果我们使用 for (NSString* key in dict) 循环遍历 dict,或者
使用 for 甚至更不具体(id key in dict) 循环然后我们实际上使用NSEnumeration。这些迭代对你来说是不可预测的。 NSEnumeration 和 NSFastEnumeration 不要使用索引迭代字典。可以这么说,它们通过地址或密钥的哈希值来遍历。这也是一个不完整的模糊答案。
字典中的键与同一字典中的其他键相比是唯一的。
这是伟大的事情,为什么你会使用NSDictionary或NSMutableDictionary而不是索引NSArray或NSPointerArray或不特定的NSSet,并特别提供数据类型为NSOrderedSet、NSOrderedCollection。 NSMapTable 和 NSHashTable 往往表现得像 NSDictionaries,但它们存储密钥和迭代的方式完全不同。
那么当你在 NSDictionary 中重写一个键值时会发生什么?
NSDictionary *dict = @{
@"A" : @(1234),
@"B" : @(4321)
}
NSMutableDictionary *mutabledict = [dict mutablecopy];
mutabledict[@"A"] = @(5678); //beware this only works on NSMutableDictionary.
dict = mutabledict;
这里我们交换第一个声明的键 A 的值。
mutabledict[@"A"] [key] 是一个 getter 下标,用于查找键的地址价值对。密钥本身没有任何改变。因此,密钥的顺序保持在复制唯一密钥的那一刻。
创建 mutablecopy 时需要小心,因为这样会复制整个对。排序的结果也可能是不可预测的。
很简单:但是访问键值不会改变它们的内存布局。
但是:NSDictionary 是不可变的,因此一旦设置了键就不能更改。所以你可以说:
这些键是按照它们第一次存储的顺序排列的。但是,当您不知道键:值对的放置顺序以及通过此过程将其唯一键复制到字典中时,您无法访问以保证顺序存储的值。
如果您无法控制设置键的顺序,那么您不知道键的顺序,(尊重问题)不是未定义的。而且 NSEnumeration 迭代无法让您真正了解它们的存储顺序。
如何处理?
获得已知的键排序排序的简单方法是手动排序所有键,例如..
NSArray *sortedKeys = [dict.allKeys sortedArrayUsingSelector:@selector(compare:)];
它为您提供键的升序,并允许您使用包含键地址的数组索引遍历您的字典。喜欢..
for (unsigned int i=0; i<sortedKeys.count; i++) {
NSString* key = sortedKeys[i];
dict[ key ] = yourValue;
}
如果键不感兴趣但保证排序对您来说更重要,那么您可以将 NSDictionary 转换为没有键的排序 NSArray 并在循环中访问其索引。除非您手动存储它们,否则明显的回画没有键。
id notfoundmarker = @"empty";
NSArray *sortedkeys= [dict.allKeys sortedArrayUsingSelector:@selector(compare:)];
NSArray *oneForOneSorted = [dict objectsForKeys:sortedkeys notFoundMarker:notfoundmarker];
for (unsigned int i=0; i<oneForOneSorted.count; i++) {
id<NSObject> value = oneForOneSorted[i];
NSLog(@"%@", value);
};