Obtenga el punto de inicio de un UIBezierPath

Creé un UIBezierPath pero no sé cómo acceder al punto de inicio. Intenté hacer esto:

let startPoint = path.currentPoint 

La propiedad currentPoint me da el último punto, no el punto de inicio. La razón por la que necesito el punto de inicio es porque quiero colocar una image en el punto de inicio de la ruta.

¿Algunas ideas?

CGPath hacia abajo a CGPath y usar CGPathApply para recorrer los elementos. Solo quieres el primero, pero tienes que mirarlos a todos.

Asumo que tu path está bien formado y comienza con un "movimiento". Eso siempre debe ser cierto para un UIBezierPath (no tengo conocimiento de ninguna forma para que no sea cierto).

Necesitarás algo de ayuda de robusta CGPath.forEach de rob mayoff, que es bastante complicado, pero con eso en su lugar es bastante sencillo:

 // rob mayoff's CGPath.foreach extension CGPath { func forEach(@noescape body: @convention(block) (CGPathElement) -> Void) { typealias Body = @convention(block) (CGPathElement) -> Void func callback(info: UnsafeMutablePointer<Void>, element: UnsafePointer<CGPathElement>) { let body = unsafeBitCast(info, Body.self) body(element.memory) } let unsafeBody = unsafeBitCast(body, UnsafeMutablePointer<Void>.self) CGPathApply(self, unsafeBody, callback) } } // Finds the first point in a path extension UIBezierPath { func firstPoint() -> CGPoint? { var firstPoint: CGPoint? = nil self.CGPath.forEach { element in // Just want the first one, but we have to look at everything guard firstPoint == nil else { return } assert(element.type == .MoveToPoint, "Expected the first point to be a move") firstPoint = element.points.memory } return firstPoint } } 

En Swift 3, básicamente es el mismo:

 // rob mayoff's CGPath.foreach extension CGPath { func forEach( body: @convention(block) (CGPathElement) -> Void) { typealias Body = @convention(block) (CGPathElement) -> Void func callback(info: UnsafeMutableRawPointer?, element: UnsafePointer<CGPathElement>) { let body = unsafeBitCast(info, to: Body.self) body(element.pointee) } let unsafeBody = unsafeBitCast(body, to: UnsafeMutableRawPointer.self) self.apply(info: unsafeBody, function: callback) } } // Finds the first point in a path extension UIBezierPath { func firstPoint() -> CGPoint? { var firstPoint: CGPoint? = nil self.cgPath.forEach { element in // Just want the first one, but we have to look at everything guard firstPoint == nil else { return } assert(element.type == .moveToPoint, "Expected the first point to be a move") firstPoint = element.points.pointee } return firstPoint } } 

La forma más simple es

-Subclass el UIBezierPath

-Crea la propiedad personalizada como startPoint

-Override el método moveToPoint y establece el valor para startPoint allí

 class MyBezierPath: UIBezierPath { var startPoint :CGPoint? override func moveToPoint(point: CGPoint) { super.moveToPoint(point) startPoint=point; } } var myBezier = MyBezierPath() myBezier.moveToPoint(CGPoint(x: 0, y: 0)) myBezier.addLineToPoint(CGPoint(x: 100, y: 0)) myBezier.addLineToPoint(CGPoint(x: 50, y: 100))