【问题标题】:Obj-C setValuesForKeysWithDictionary 64-bit vs 32-bitObj-C setValuesForKeysWithDictionary 64 位与 32 位
【发布时间】: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


【解决方案1】:

NSDictionary 对象是无序的集合,因此代码不应该对字典枚举其自己的键的顺序做出假设。事实证明,32 位和 64 位运行时之间存在实现差异,这些差异会影响散列值最终存储的位置。

由于 API 合同明确不保证顺序,这不应该导致问题,但它可以(在这种情况下显然确实)具有导致以前代码的副作用'在为 64 位架构编译时工作'会中断。

在不显着更改实现的情况下解决您当前遇到的问题的一种快速方法是自己枚举字典的键,这将允许您提供按您希望排序的键数组:

- (void)setAttributesFromDictionary:(NSDictionary *)dictionary
{
    // So instead of doing this...
    //
    // [self setValuesForKeysWithDictionary:dictionary];

    // You could do something along these lines:
    //
    NSMutableArray *keys = dictionary.allKeys.mutableCopy;

    // TODO: insert code to change the order of the keys array.
    // Then loop through the keys yourself...

    for (NSString *key in keys)
    {
        [self setValue:dictionary[key] forKey:key];
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-21
    • 1970-01-01
    • 1970-01-01
    • 2014-01-04
    • 2011-09-24
    • 2012-02-11
    • 2010-11-27
    • 1970-01-01
    相关资源
    最近更新 更多