Swift Can';在将UIView添加到当前UIView后,无法访问子层

Swift Can';在将UIView添加到当前UIView后,无法访问子层,swift,uiview,cashapelayer,Swift,Uiview,Cashapelayer,我画了一堆现金图层,所以我需要检测我触摸的是哪一个,所以我用这个 if let sublayers = self.layer.sublayers as? [CAShapeLayer]{ //get all CAShape and stored as an array print("loop sublayer") for layer in sublayers{ // go through each CAShape

我画了一堆现金图层,所以我需要检测我触摸的是哪一个,所以我用这个

if let sublayers = self.layer.sublayers as? [CAShapeLayer]{ //get all CAShape and stored as an array
            print("loop sublayer")
            for layer in sublayers{ // go through each CAShape
                print("loop layer")
                if let path = layer.path, path.contains(currentPanPoint) { // if there is a path at that point then return, else create a path
                    print("detecting")
                    startPointOfTouchedRuler = detectWhichRuler(layer: layer)
                    if startPointOfTouchedRuler != zeroPoint{
                        //  drawCircle(point: startPointOfTouchedRuler)
                        break
                    }else{
                    }
                }
            }
        }
现在我想在创建CAShapeLayer时添加一个UIView,以便更轻松地管理和移动它们,我使用它在CAShapeLayer位置添加一个新的UIView:

  func createUIViewOutSideRuler(startPoint:CGPoint, currentPoint:CGPoint, angle: CGFloat){
        let viewWidth = distanceFromTwoPoints(startPoint, currentPoint)
        print(viewWidth)
        let view = UIView(frame: CGRect(x:currentPoint.x, y: currentPoint.y , width:  viewWidth, height: dotLineSize * 3))
        view.backgroundColor = .orange
        view.transform = CGAffineTransform(rotationAngle: angle);
        
        self.addSubview(view)
    }

添加新的UIview后,获取CAShapeLayer的循环根本不会启动,命令行不会打印
print(“循环子层”)

p/S:也适用于标签、按钮等。如果在添加
UIView
UIButton
后,我打印(self.layer.sublayers为?[CAShapeLayer]),它将返回
nil



快速解释:

if let sublayers = self.layer.sublayers as? [CAShapeLayer] {} else {}

当您将self.layer.sublayers作为?[CAShapeLayer],假设所有
self.layer.sublayer
都属于
CAShapeLayer
类型。但是,你确定吗,谁告诉你的?还有其他类型的
CALayer
,默认组件可能已经附带了一些。这就是它失败的原因。其思想是使用
compactMap()
仅保留
CAShapeLayer

let sublayers = self.layer.sublayers.compactMap { $0 as? [CAShapeLayer] }
详细说明:

if let sublayers = self.layer.sublayers as? [CAShapeLayer] {} else {}

之所以调用
else
,是因为
self.layer.sublayers
不能装入,它不是[CAShapeLayer]。在我们的例子中,它们是层,所以这意味着并非所有的子层都是
CAShapeLayer
。 因此,让我们只保留
CAShapeLayer
,而忘记另一个(
CAGradientLayer
CALayer
,等等)。 为此,我们可以使用
compactMap()

闭包逻辑很简单: 数组被迭代。在每次迭代中,该项被称为
aSublayer
。我们想做什么就做什么,如果需要,我们返回一个转换后的值,一个Int,等等。 如果不想保留转换后的值,则返回nil,然后将跳过它

由于我们只想保留属于
CAShapeLayer
的子层,因此可以对其使用简单的强制转换:

if let aSubLayerAsShapeLayer = aSubLayer as? CAShapeLayer {
    return aSubLayerAsShapeLayer
} else { //We won't keep it
    return nil
}
这相当于

return aSubLayer as? CAShapeLayer
然后,通过进一步简化(来自单表达式闭包的隐式返回,
速记参数名称
,有关的更多信息),我们得到:


此外,由于它“肯定”有一个数组(可能是空的),它不再是可选的,我们将
if let
删除为
let

您能检查
self.layer.sublayers
是否为空吗?如果不是,则由于演员阵容,您的线路为零。=>
let sublayers=self.layer.sublayers.flatMap{$0 as?CAShapeLayer}
?所有子层可能不是一个
CAShapeLayer
,而是另一个层?
self.layer。子层
不是空的,但当我将其设置为CAShapeLayer时,它返回
nil
let sublayers=self.layer.sublayers.flatMap{$0 as?CAShapeLayer}
得到警告
从“[CALayer]”到不相关类型“CAShapeLayer”的转换总是失败
,并且还返回
nil
“但是当我按照我的建议将其设置为CAShapeLayer时”?因为如果它像你的代码,那么它显然会失败。另外,您添加了一个子视图?但是,形状层在该视图上,而不是在初始视图上?编辑:我的意思是
compactMap()
,而不是
flatMap()
,我试过,
flatMap
,但没有成功。我的新形状层仍在初始形状层上,我刚刚创建了一个新的UIView,没有对它做任何操作。我的意思是
compactMap
,而不是
flatMap()
,我的错。
let sublayers = self.layer.sublayers.compactMap { $0 as? [CAShapeLayer] }