#swift #uibezierpath
#swift #uibezierpath
Вопрос:
Я пытаюсь нарисовать несколько с помощью UIBezierPath, но всякий раз, когда я пытаюсь нарисовать 2-ю, первая исчезает. Пытался создать несколько 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
}
}
Комментарии:
1. С помощью представленного вами кода вы создаете новую
UIBezierPath
каждый раз, когда запускается распознаватель жестов. Вы захотите сохранить свойlinePath
как экземпляр в своем классе, а затем в.begin
состоянии повторно инициализировать путь и.move(to:)
точку.2.Я попробовал то, что вы предложили, и она все еще исчезает, когда начинает рисоваться вторая строка. Теперь она рисует другую линию всякий раз, когда я перемещаю мышь, вместо того, чтобы быть растянутой. Я создаю экземпляр
var linePath:UIBezierPath?
и инициализирую в.begin
linePath = UIBezierPath()
Ответ №1:
Из-за 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
}
}