You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UIView.draw(rect:)调用未绘上下文:多进度条实例绘制异常

问题:自定义UIView多实例绘制异常,仅第一个显示圆弧

iOS开发新手,在自定义UIView(MyProgressView)的draw(rect:)方法中通过UIGraphicsGetCurrentContext绘制圆弧进度条,单个实例显示正常,但创建多个实例时,只有第一个能正确绘制,其余实例的draw(rect:)虽被调用却无图形输出。运行环境为iOS15.4的Playground。

自定义视图代码

class MyProgressView: UIView {
    
    var startAngle: Double = 0.0
    var endAngle: Double = 0.0 {
        didSet{
            self.setNeedsDisplay()
        }
    }
    
    
    func radian(_ degree: Double) -> Double {
        return (degree - 90) * Double.pi / 180.0
    }
        
    override func draw(_ rect: CGRect) {
        guard let context = UIGraphicsGetCurrentContext() else { return }
        context.setLineWidth(10)
        context.setStrokeColor(UIColor.white.cgColor)
        context.addArc(center: self.center, radius: 30, startAngle: radian(startAngle), endAngle: radian(endAngle), clockwise: false)
        context.strokePath()
        
    }
}

视图控制器viewDidLoad代码

let progressBar = MyProgressView()
progressBar.frame = CGRect(x: 0, y: 0, width: view.frame.width / 2, height:view.frame.height / 2)
progressBar.backgroundColor = .systemMint
progressBar.startAngle = 0
progressBar.endAngle = 180
view.addSubview(progressBar)

let progressBar2 = MyProgressView()
progressBar2.frame = CGRect(x: 150, y: 0, width: view.frame.width / 2, height: view.frame.height / 2)
progressBar2.backgroundColor = .systemPink
progressBar2.startAngle = 90
progressBar2.endAngle = 270
view.addSubview(progressBar2)

let progressBar3 = MyProgressView()
progressBar3.frame = CGRect(x: 0, y: 150, width: view.frame.width / 2, height: view.frame.height / 2)
progressBar3.backgroundColor = .systemIndigo
progressBar3.startAngle = 90
progressBar3.endAngle = 270
view.addSubview(progressBar3)

问题原因

self.center是当前视图在父视图坐标系下的中心点坐标,而draw(rect:)方法的绘图上下文是基于当前视图自身的坐标系(原点在视图左上角,x轴向右,y轴向下)。

  • 第一个视图的frame是(0,0,w/2,h/2),它的center是(w/4, h/4),这个坐标在自身的rect范围内,所以圆弧能正常显示。
  • 第二个视图的frame是(150,0,w/2,h/2),它的center是(150 + w/4, h/4),但在自身绘图上下文里,x轴最大范围是w/2,这个center的x值远超出自身宽度,导致圆弧绘制在视图外部,自然看不到。
  • 第三个视图同理,center的y值超出自身高度范围,圆弧也绘制在视图外面。

解决方案

将圆弧的中心点改为当前视图自身rect的中心,也就是使用rect.midX和rect.midY构建坐标,而非self.center。

修改后的draw(rect:)方法代码:

override func draw(_ rect: CGRect) {
    guard let context = UIGraphicsGetCurrentContext() else { return }
    context.setLineWidth(10)
    context.setStrokeColor(UIColor.white.cgColor)
    // 使用当前视图自身rect的中心作为圆弧中心点
    let center = CGPoint(x: rect.midX, y: rect.midY)
    context.addArc(center: center, radius: 30, startAngle: radian(startAngle), endAngle: radian(endAngle), clockwise: false)
    context.strokePath()
}

内容的提问来源于stack exchange,提问作者Joon Mo Park

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 05:30:50