UIBezierPath 线在绘制另一条时消失

UIBezierPath line disappears when drawing another one

我正在尝试使用 UIbezierPath 绘制多个,但每当我尝试绘制第二个时,第一个就会消失。试图创建多个 BezierPath 并将它们放入一个数组但是当它 运行 进入 case:ended

时我得到了这个错误

test[2687:238999] [Unknown process name] CGPathCloseSubpath: no current point.

这是我的代码


 private lazy var lineShape: CAShapeLayer = {
        let lineShape = CAShapeLayer()
        lineShape.strokeColor = UIColor.blue.cgColor
        lineShape.lineWidth = 2.0

        return lineShape
    }()
    
 var bezierPathArr:NSMutableArray = []
 private var panGestureStartPoint: CGPoint = .zero
 private lazy var panRecognizer: UIPanGestureRecognizer = {
        return UIPanGestureRecognizer(target: self, action: #selector(panGestureCalled(_:)))
    }()

 @objc func panGestureCalled(_: UIPanGestureRecognizer) {
        let linePath = UIBezierPath()
        let currentPanPoint = panRecognizer.location(in: self.view)
        switch panRecognizer.state {
        case .began:
            panGestureStartPoint = currentPanPoint
            self.view.layer.addSublayer(lineShape)
            bezierPathArr.add(linePath)

        case .changed:
            linePath.move(to: panGestureStartPoint)
            linePath.addLine(to: currentPanPoint)
            lineShape.path = linePath.cgPath

        case .ended:
            let finalPath:UIBezierPath = bezierPathArr.lastObject as! UIBezierPath
            finalPath.close()
    
        default: break
        }
    }


由于 lazy 创建了您的 CAShapeLayer,无论何时向视图添加层,您都在使用相同的对象引用。连同在该参考上设置路径将为您提供您正在经历的行为。

为了实现预期的行为,您需要为每个完成的手势创建并存储一个新的 CAShapeLayer。这是一个工作示例:

class ViewController: UIViewController {
    
    private lazy var panRecognizer: UIPanGestureRecognizer = {
        return UIPanGestureRecognizer(target: self, action: #selector(panGestureCalled(_:)))
    }()
    
    /// The path that is being drawn (resets on .began, closes on .ended)
    private var currentPath: UIBezierPath = .init()
    /// All of the layers added to the view
    private var shapes: [CAShapeLayer] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.addGestureRecognizer(panRecognizer)
    }

    @objc private func panGestureCalled(_ sender: UIPanGestureRecognizer) {
        let point = sender.location(in: self.view)
        switch sender.state {
        case .began:
            // Reset the path
            currentPath = .init()
            // Set the starting point
            currentPath.move(to: point)
            // Creates a new layer when gesture starts.
            let layer = newShapeLayer()
            // Save the layer with all shapes.
            shapes.append(layer)
            // Add the layer to the view
            view.layer.addSublayer(layer)
        case .changed:
            // Update the current path to the new point
            currentPath.addLine(to: point)
        case .ended:
            // Close/Finish the path
            currentPath.close()
        default:
            break
        }
        
        // Update the most-current shape with the path being drawn.
        shapes.last?.path = currentPath.cgPath
    }
    
    /// Creates a new `CAShapeLayer`
    private func newShapeLayer() -> CAShapeLayer {
        let layer = CAShapeLayer()
        layer.frame = view.bounds
        layer.strokeColor = UIColor.blue.cgColor
        layer.lineWidth = 2.0
        return layer
    }
}