【问题标题】:Why does this code behave differently on 64 bit builds? (iOS / UIColor / UIKeyedArchiver)为什么这段代码在 64 位版本上表现不同? (iOS / UIColor / UIKeyedArchiver)
【发布时间】:2014-03-11 23:07:47
【问题描述】:

代码:

UIColor * color = [UIColor colorWithHue:0.3 saturation:0.2 brightness:0.2 alpha:1];
CGFloat r,g,b,a;

[color getRed:&r green:&g blue:&b alpha:&a];

NSData * colorData = [NSKeyedArchiver archivedDataWithRootObject:color];
UIColor * unarchivedColor = [NSKeyedUnarchiver unarchiveObjectWithData:colorData];

[unarchivedColor getRed:&r green:&g blue:&b alpha:&a];


正如预期的 32 位版本,unarchivedColor 和 color 具有完全相同的 rgb 值。在 arm64 构建中,unarchivedColor 和 color 开始在小数点后 9 位左右开始不同。

换句话说,归档/取消归档 UIColor 会修改 arm64 上的颜色...我不希望这种情况发生。这是怎么回事,有没有办法解决这个问题?

【问题讨论】:

    标签: ios iphone objective-c ipad nscoding


    【解决方案1】:

    差异可能是因为在 32 位上,CGFloatfloat,而在 64 位下是 double

    尝试使用double 而不是CGFloat。或者只是接受这样一个事实,即在 64 位下,您将获得更高的精度值。

    【讨论】:

    • 这是一个 UIColor 对象,所以我无法控制内部 double/CGFloat 属性。我宁愿不重写整个 UIColor 类。另外 - 我不能只是接受它,因为每次保存颜色时,它的值都会略微修改。这不会导致我的应用程序崩溃,但会导致错误。我不认为代码假设在正常情况下,如果一个对象被保存然后再次打开,它会和之前一样......不是这样的行为表明有问题是不合理的?跨度>
    • 但是您可以控制使用CFGloatfloatdouble 作为r,g,b,a 变量。您还可以选择归档 4 个单独的值,而不是 UIColor
    • 我只是在查看 r g b 值以找出问题所在。它是正在归档的 UIColor 对象。做你建议的假设一个恒定的色彩空间,对我来说,这意味着改变应用程序的数据结构,这不仅仅是一项微不足道的任务。
    • 我对此了解不多,但也许为 UIColor 编写我自己的 64 位安全 NSCoding 实现可以解决问题?
    【解决方案2】:

    通过 Apple 技术支持事件确认这是与 arm64 上的归档类相关的错误。他们的建议是构建一个自定义归档器类。

    【讨论】:

      【解决方案3】:

      这不再是问题(或者也许从来都不是问题)。

      UIColor * color = [UIColor colorWithHue:0.3 saturation:0.2 brightness:0.2 alpha:1];
      NSData * colorData = [NSKeyedArchiver archivedDataWithRootObject:color];
      UIColor * unarchivedColor = [NSKeyedUnarchiver unarchiveObjectWithData:colorData];
      
      CGFloat r, g, b, h, s, a;
      [color getHue:&h saturation:&s brightness:&b alpha:&a];
      NSLog(@"HSBA %f %f %f %f", h, s, b, a);
      [unarchivedColor getHue:&h saturation:&s brightness:&b alpha:&a];
      NSLog(@"unarchived HSBA %f %f %f %f", h, s, b, a);
      
      [color getRed:&r green:&r blue:&b alpha:&a];
      NSLog(@"RGB %f %f %f %f", r, g, b, a);
      [unarchivedColor getRed:&r green:&r blue:&b alpha:&a];
      NSLog(@"unarchived RGB %f %f %f %f", r, g, b, a);
      

      结果(格式化)

      HSBA            0.300000 0.200000 0.200000 1.000000
      unarchived HSBA 0.300000 0.200000 0.200000 1
      RGB             0.200000 0.000000 0.160000 1.000000
      unarchived RGB  0.200000 0.000000 0.160000 1.000000
      

      然而,使用 HSBA 值构造 UIColor 对象而未选择 arm64,将其归档,然后在 arm64 下取消归档,将在恢复时导致不同的 HSBA 值,因为64 位的不同精度级别。

      【讨论】:

      • 这肯定是个问题。由帮助编写该框架部分的 Apple 工程师确认,而不仅仅是您的默认 Apple 技术支持响应者。很高兴知道它已被修复。
      猜你喜欢
      • 2011-10-10
      • 2020-07-23
      • 1970-01-01
      • 2011-11-24
      • 2017-04-22
      • 2010-11-01
      • 2011-04-07
      • 1970-01-01
      相关资源
      最近更新 更多