为啥在子视图中添加图层蒙版时需要调用 layoutIfNeeded()?

Posted

技术标签:

【中文标题】为啥在子视图中添加图层蒙版时需要调用 layoutIfNeeded()?【英文标题】:Why do I need to call layoutIfNeeded() when adding a layer mask to a subview?为什么在子视图中添加图层蒙版时需要调用 layoutIfNeeded()? 【发布时间】:2017-02-28 22:34:18 【问题描述】:

我的主视图有一个子视图,我使用以下扩展添加了一个掩码:

extension UIView
func addTopRoundCorners()
    let bezierPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: [UIRectCorner.topLeft, UIRectCorner.topRight], cornerRadii: CGSize(width: 20, height: 20))
    let maskLayer = CAShapeLayer()
    maskLayer.path = bezierPath.cgPath
    maskLayer.fillColor = UIColor.red.cgColor
    self.layer.mask = maskLayer

我注意到此代码对我的子视图的影响只有在我在主视图上调用layoutIfNeeded() 时才会出现在屏幕上,然后再将掩码添加到我的子视图。如果有人能向我解释这是为什么,我将不胜感激?

【问题讨论】:

你在使用自动布局吗? 您对视图生命周期的理解程度如何?通俗地说,您是在告诉操作系统重新绘制所需的内容。 是的,我正在使用自动布局。但是,我通过代码而不是情节提要添加了它们。我也知道在使用自动布局时,您必须调用 layoutIfNeeded() 才能使蒙版起作用,但为什么呢? @apineda 我有点眼熟。 @dfd 那我可能不清楚你在问什么。您向视图添加一些东西——一个层、一个子视图、一个滑块变化,等等——并且需要向操作系统发出信号来更新东西。某些更改(很可能是用户交互)会自动触发此更新。但其他人(添加一个子层,取决于你什么时候做)不需要,因此需要一些东西来触发操作系统来刷新东西。听起来你知道这一点。但如果是这样,那你在问什么?希望这是有道理的。 【参考方案1】:

layoutIfNeeded 将计算视图的位置和大小。如果在计算最终位置和大小之前调用addTopRoundCorners() 函数,那么用于创建UIBezierPathself.bounds 将是错误的。

自动布局不会自动调整遮罩层的大小,也不会调用addTopRoundCorners 重新创建路径。

【讨论】:

以上是关于为啥在子视图中添加图层蒙版时需要调用 layoutIfNeeded()?的主要内容,如果未能解决你的问题,请参考以下文章

Swift mapview图层蒙版裁剪/移动视图。我究竟做错了什么?

GeoServer中配置的图层使用OpenLayers为啥读不出来

如何获得圆形图层蒙版?

在视网膜 iPad 上应用图层蒙版会隐藏所有

28.图层蒙版及图层混合模式

iOS 图层蒙版在 UIStackView 上不起作用