为啥必须使用 CALayer 的presentationLayer 进行命中测试?

Posted

技术标签:

【中文标题】为啥必须使用 CALayer 的presentationLayer 进行命中测试?【英文标题】:Why does one have to use CALayer's presentationLayer for hit-testing?为什么必须使用 CALayer 的presentationLayer 进行命中测试? 【发布时间】:2010-02-04 11:17:03 【问题描述】:

我正在开发一个 Cocoa Touch 应用程序,并尝试通过确定视图层的哪个子层被触摸来处理触摸。我的控制器代码如下所示:

CALayer *hitLayer = [self.view.layer hitTest:point];

这不起作用。如果我在子层的底部点击它会起作用,但不是在顶部。经过一个小时的拉扯和谷歌搜索,我终于发现如果使用表示层而不是层本身进行命中测试,它会起作用:

CALayer *hitLayer = [self.view.layer.presentationLayer hitTest:point];

所以,我已经解决了我的问题,但我的问题是:为什么?

我已通读 Core Animation 指南,并且了解表示树和渲染树可能与对象模型树不同。但我不明白为什么表示树(显然)会有不同的命中测试行为。表示树和对象模型不会有相同的框架、边界等吗?

【问题讨论】:

self.view的类是什么:UIView还是CALayer? self.view 是一个 UIView。我已经更正了上面的代码以使用“self.view.layer”,因为它应该是。 【参考方案1】:

根据CALayer documentation,模型和展示树之间在展示给用户的内容方面似乎存在差异(取决于正在进行的动画)。对于命中测试,presentationLayer方法中有参考:

例如,发送一个 hitTest: 给presentationLayer的消息将 查询的表示值 层树。

所以我怀疑只有表示层有正确的几何信息来执行命中测试。

【讨论】:

【参考方案2】:

Kristopher,我也有一个非常相似的问题。但是,当我将点转换为超级图层或超级视图坐标系时,它工作得很好。我没有使用表示层。

    //Identify the touch point in the view. Using UITapRecognizer
CGPoint loc = [recognizer locationInView:recognizer.view];

//convert the point to superview co-ordinates and then identify the layer using hit test.
CALayer *layer = [self.layer hitTest:[self convertPoint:loc toView:self.superview]];

这会返回我被触摸的层,至少现在是这样。如果您认为这是一种错误的方法,请告诉我们,我应该改用表示层。

【讨论】:

以上是关于为啥必须使用 CALayer 的presentationLayer 进行命中测试?的主要内容,如果未能解决你的问题,请参考以下文章

为啥masksToBounds = YES会阻止CALayer阴影?

为啥 UIView Animation 不会触发 CALayer 的 addAnimation:forKey:?

为啥 CALayer 蒙版没有居中并偏离几个像素?

为啥我们不能把 UIView 的子视图放在它的 CALayer 前面?

为啥动画自定义 CALayer 属性会导致其他属性在动画期间为零?

为啥 NSShadow 和 CALayer 的 shadowOffset 通过 CGSize 类型而不是 CGPoint 类型表示