我遇到了一个问题,即当值变大时,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
,因此当CGFloat
为double
时,它将失去精度。 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上,其中
CGFloat
是double
,输出1000000001.000000
因此,在
CALayer
公共(public)Objective-C类级别上,精度没有损失。 QuartzCore中还有其他地方可以转换为单精度float
。我建议使用小于2 ^ 24的整数(包括加法结果)。鉴于
zPosition
具有浮点类型,您可以使用较小的分数值而不是较大的整数值。