【发布时间】:2015-03-26 13:21:29
【问题描述】:
我正在从我的 API 中提取一个 JSON 对象并使用以下代码创建它(事后看来,这不是可行的方法):
+ (YActivity *)instanceFromDictionary:(NSDictionary *)jsonDictionary
{
YActivity * instance = [[YActivity alloc] init];
[instance setAttributesFromDictionary:jsonDictionary];
return instance;
}
- (void)setAttributesFromDictionary:(NSDictionary *)jsonDictionary
{
if (![jsonDictionary isKindOfClass:[NSDictionary class]]) {
return;
}
[self setValuesForKeysWithDictionary:jsonDictionary];
}
其中一个键是“类型”。我有一个名为“type”的只读变量@synthesized。在我的应用程序的 32 位版本上,这是在调用 setValue:(id)value forUndefinedKey:(NSString *)key 之前立即设置的。我在那个方法中引用了这个值,在我的应用程序的 64 位版本上,当断点命中这个方法时,类型还没有设置。
显然这不是最好的做法。我只是想知道是否有其他人看到了这一点,或者我是否在吠叫错误的树。我区分了两个版本之间的文件,它们是相同的。我在 iOS 8.1 模拟器上运行它们,API 为两者返回相同的东西......我很难过。基本上在旧版本中定义的键是在未定义之前设置的,而在新版本中似乎相反。
【问题讨论】:
-
字典是无序的集合;代码不应该对字典键的枚举顺序做出假设。
-
是的,如前所述,这里显然不正确。想知道是否有人知道这些方法的顺序是否在某个时候发生了变化。依赖字典的序列化是不对的。
-
不确定“这些方法的顺序”是什么意思。各种不同对象类型产生的哈希值在 64 位和 32 位系统上可能不同,因此这可能是您看到的差异的原因。
-
根据 CFDictionary.c,存储桶大小也在 32 位和 64 位运行时之间变化。 Apple 已执行其对对象顺序的非保证。
-
@JeffN 一些潜在的快速修复: 1) 不要调用
setValuesForKeysWithDictionary:,而是从你自己枚举键的循环中调用setValue:forKey:;这样您就可以按照自己喜欢的方式订购钥匙;或 2) 在调用setValuesForKeysWithDictionary:之前,创建字典的可变副本,删除type的键值对,调用setValue:forKey:和type及其值;那么您可以安全地传递可变字典而不是原始字典。
标签: ios objective-c json nsdictionary 32bit-64bit