我遇到了一个问题,即当值变大时,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位置的值较小,则此功能可以按预期运行。即使子层数组未正确排序,顶层仍显示在底层上方,如下所示:

但是,对于上面显示的示例,结果如下:

显然这是不正确的。

问题

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

最佳答案

那是因为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公共(public)Objective-C类级别上,精度没有损失。 QuartzCore中还有其他地方可以转换为单精度float

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

10-08 07:53