将UIView添加到当前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
                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("loop sublayer")

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


解决方法

快速说明:

当您执行self.layer.sublayers as? [CAShapeLayer]时,您假设所有self.layer.sublayers的类型均为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,而忽略另一个(CAGradientLayerCALayer等)。 为此,我们可以使用compactMap()

self.layer.sublayers.compactMap { aSublayer in
 
}

关闭逻辑很简单: 数组被迭代。在每次迭代中,该项目称为aSublayer。我们做我们想做的任何事情,并在需要时返回一个转换后的值,一个Int等。 如果我们不想保留转换后的值,则返回nil,然后将其跳过。

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

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

等同于

return aSubLayer as? CAShapeLayer

然后,通过进一步简化(单次表达闭包的隐式收益,Shorthand Argument Names,有关doc的更多信息),我们得到:

let sublayers = self.layer.sublayers.compactMap { $0 as? [CAShapeLayer] }

此外,由于“确定”具有数组(可能为空),因此不再是可选的,我们将if let移到let中。