Reputation: 1395
I'm trying to draw multiple with UIbezierPath but whenever I try to draw the 2nd one, the first one disappears. Tried to create multiple BezierPath and put them into an array but I got this error when it run into case:ended
test[2687:238999] [Unknown process name] CGPathCloseSubpath: no current point.
This is my code
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
}
}
Upvotes: 1
Views: 175
Reputation: 1589
Because of the lazy
creation of your CAShapeLayer
, whenever you are adding a layer to your view, you are using the same object reference. That along with setting the path on that reference would give you the behavior you are experiencing.
In order to achieve the behavior expected, you need to create and store a new CAShapeLayer
for each of your completed gestures. Here's a working example:
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
}
}
Upvotes: 1