Swift UIView调用draw后如何用UIBezierPath追加绘制图形?
问题解决思路
你的问题出在iOS的绘制机制上:draw(_:)是系统管理的专属绘制入口,只有这个方法内的绘制操作才会被正确渲染并持久化;直接在外部调用drawArrow()时,没有处于有效的图形上下文环境中,绘制内容无法被保留,而且下次draw(_:)执行时会覆盖所有临时绘制结果。
另外你提供的控制器代码遗漏了将bezierView添加到父视图的步骤(不过从你的输出图看主路径已显示,推测实际代码里补充了这一步,但仍需注意规范)。
修正方案
1. 修改BezierView,用状态变量控制绘制
把箭头的绘制逻辑整合到draw(_:)方法中,通过布尔变量控制是否绘制箭头:
final class BezierView: UIView { var currentPoint: CGPoint = CGPoint() // 新增状态变量:控制是否绘制箭头 var shouldDrawArrow = false override func draw(_ rect: CGRect) { // 绘制主路径 let line1 = UIBezierPath() line1.move(to: CGPoint(x: 20, y: 65)) line1.addLine(to: CGPoint(x: 20, y: 15)) line1.addLine(to: CGPoint(x: self.frame.width - 20, y: 5)) line1.addLine(to: CGPoint(x: self.frame.width - 20, y: 65)) line1.lineWidth = 2 UIColor.darkGray.setStroke() line1.stroke() currentPoint = line1.currentPoint // 根据状态决定是否绘制箭头 if shouldDrawArrow { drawArrow() } } private func drawArrow() { let point = currentPoint let arrowTip = UIBezierPath() arrowTip.move(to: point) arrowTip.addLine(to: CGPoint(x: point.x - 6, y: point.y - 6)) arrowTip.addLine(to: CGPoint(x: point.x + 6, y: point.y - 6)) arrowTip.close() UIColor.darkGray.setFill() arrowTip.fill() } }
2. 修改控制器代码,正确触发重绘
设置状态变量后,调用setNeedsDisplay()通知系统触发重绘:
override func viewDidLoad() { super.viewDidLoad() let bezierView = BezierView(frame: CGRect(x: 0, y: 40, width: self.view.frame.width, height: 200)) view.addSubview(bezierView) // 必须添加到父视图才能显示 // 开启箭头绘制并触发重绘 bezierView.shouldDrawArrow = true bezierView.setNeedsDisplay() }
核心原理
iOS的视图绘制由系统统一调度,只有在draw(_:)方法内,系统才会创建并传递有效的图形上下文(CGContext)。所有需要持久化的绘制操作都应该放在这个方法里,外部通过修改状态变量+调用setNeedsDisplay()触发更新,系统会重新调用draw(_:),根据最新状态完成完整绘制。
内容的提问来源于stack exchange,提问作者Mehmet Ali Kısacık
相关产品推荐
相关产品推荐

