CALayer zPosition排序具有极大的值

时间:2014-08-01 00:40:41

标签: ios macos core-animation

我遇到了一个问题,当值变大时,Core Animation似乎忽略了zPosition的值。

实施例

这可以很容易地复制。

CGFloat largeZPosition = 1000000000;

CALayer *topLayer = ...
CALayer *bottomLayer = ...
bottomLayer.frame = CGRectOffset(topLayer.frame, 50, 50);

topLayer.zPosition = largeZPosition + 1;
bottomLayer.zPosition = largeZPosition;

// Intentionally sort the sublayers array in the wrong order.
rootLayer.sublayers = @[ topLayer, bottomLayer ];

z值位置值较小时,按预期运行。即使子层数组未正确排序,顶层也会显示在底层之上,如下所示:

correct

但是,如上所示,结果如下:

enter image description here

显然这不正确。

问题

根据我的需要,我无法对子图层数组进行手动排序,因此我依靠zPosition按预期执行。所以我的问题是:我该如何解决这个问题?感谢。

1 个答案:

答案 0 :(得分:12)

这是因为QuartzCore似乎正在将zPosition转换为float,所以当CGFloatdouble时它会失去精确度。 IEEE单精度浮点数使用24位表示有效位和精度,因此可能无法精确表示大于2 ^ 24的整数。例如,

float largeZPosition = 1000000000;
float largeZPositionPlus1 = 1000000001;
NSLog(@"%f %f %d", largeZPosition, largeZPositionPlus1, largeZPosition == largeZPositionPlus1);

输出

1000000000.000000 1000000000.000000 1

下一个可精确表示的整数是1000000064。

请注意,CALayer.zPosition定义为CGFloat,只要基础CGFloat能够做到这一点,它就能够保持大于2 ^ 24的整数值。检查

layer.zPosition = 1000000001;
NSLog(@"%f", layer.zPosition);

在64位OS X上,CGFloatdouble,输出

1000000001.000000

所以,在CALayer公共Objective-C类级别,精度并没有丢失。 QuartzCore还有其他地方可以转换为单精度float

我建议使用小于2 ^ 24的整数(包括加法结果)。鉴于zPosition具有浮点类型,您可以使用较小的小数值而不是大的整数值。