Following this answer, I implemented a CanvasView for drawing using the Apple Pencil: https://stackoverflow.com/a/4176268
import Foundation import UIKit class CanvasView: UIView { var points: [CGPoint]? var path: UIBezierPath? var pathLayer: CAShapeLayer! override func layoutSubviews() { } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { pathLayer = CAShapeLayer() pathLayer.fillColor = UIColor.clear.cgColor pathLayer.strokeColor = UIColor.red.cgColor pathLayer.lineWidth = 3 self.layer.addSublayer(pathLayer) if let touch = touches.first { points = [touch.location(in: self)] } } override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { if let touch = touches.first { if #available(iOS 9.0, *) { if let coalescedTouches = event?.coalescedTouches(for: touch) { points? += coalescedTouches.map { $0.location(in: self) } } else { points?.append(touch.location(in: self)) } if let predictedTouches = event?.predictedTouches(for: touch) { let predictedPoints = predictedTouches.map { $0.location(in: self) } pathLayer.path = UIBezierPath(catmullRomInterpolatedPoints: points! + predictedPoints, closed: false, alpha: 0.5)?.cgPath } else { pathLayer.path = UIBezierPath(catmullRomInterpolatedPoints: points!, closed: false, alpha: 0.5)?.cgPath } } else { points?.append(touch.location(in: self)) pathLayer.path = UIBezierPath(catmullRomInterpolatedPoints: points!, closed: false, alpha: 0.5)?.cgPath } } } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { pathLayer.path = UIBezierPath(catmullRomInterpolatedPoints: points!, closed: false, alpha: 0.5)?.cgPath points?.removeAll() } } extension UIBezierPath {
Unfortunately, this is not so smooth, because some points are outside the line, which you can see here: 
I tried disabling the predicted strokes, but that doesn't help much. What else can I do to optimize this?
source share