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

调用setNeedsDisplay后drawRect函数未触发的绘图问题求助

问题分析与修复方案

核心问题

  1. vGraphs实例未加入视图层级:创建vGraphs对象后未将其添加到graphCanvas的子视图中,系统无法触发它的draw(_:)方法。
  2. 绘图操作脱离绘制上下文:plotGraph中的NSBezierPath绘制代码直接调用,此时无有效图形上下文(仅draw(_:)执行时系统才会提供上下文),导致抛出invalid context错误。
  3. 类名不符合Swift规范:Swift类名需用大驼峰命名(如Main而非main),避免与系统API冲突。

修复后的完整代码

// 遵循Swift命名规范,类名首字母大写
class Main: NSViewController {
    
    @IBOutlet weak var targetView: NSView!
    
    func plotGraph(){
        let graphManager = clGraphs()
        graphManager.initialize(graphCanvas: targetView, controller: self)
        graphManager.processData()
        graphManager.plotline()
    }
}

class clGraphs {
    
    weak var controller: NSViewController? // 使用weak避免循环引用
    var graphCanvas: NSView!
    
    var lineData = [Float]()
    
    // 调整初始化方法,直接配置属性无需返回自身
    public func initialize(graphCanvas: NSView, controller: NSViewController) {
        self.graphCanvas = graphCanvas
        self.controller = controller
    }
    
    public func plotline(){
        let lb = NSTextField(frame: NSRect(x: 10, y: 10, width: 100, height: 20))
        lb.stringValue = "Test"
        graphCanvas.addSubview(lb)
        
        // 创建vGraphs实例并设置其frame匹配父视图 bounds
        let graphView = vGraphs(frame: graphCanvas.bounds)
        // 设置自动调整尺寸,随父视图变化适配
        graphView.autoresizingMask = [.width, .height]
        // 将graphView加入视图层级,触发绘制周期
        graphCanvas.addSubview(graphView)
        graphView.needsDisplay = true
    }
    
    public func processData(){
        // 添加测试用线条数据
        lineData = [10, 50, 30, 80, 60]
    }
}

class vGraphs: NSView{
    
    var lineData = [Float]()
    
    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)
        
        print("In the draw rect function")
        
        // 绘制背景填充(可选)
        NSColor.lightGray.setFill()
        dirtyRect.fill()
        
        // 绘制测试线条
        let aPath = NSBezierPath()
        aPath.move(to: NSPoint(x: 50, y: 50))
        aPath.line(to: NSPoint(x: 200, y: 200))
        aPath.lineWidth = 10
        NSColor.red.setStroke() // 设置线条颜色
        aPath.stroke()
    }
    
    // 移除自定义的setNeedsDisplay重写,使用系统默认实现即可
}

关键修改点说明

  • 加入视图层级:通过graphCanvas.addSubview(graphView)将vGraphs实例加入视图树,确保系统识别并触发其绘制流程。
  • 绘图逻辑移至draw(_:):所有绘图操作必须放在draw(_:)方法内,此时系统会自动提供有效图形上下文,解决invalid context错误。
  • 避免循环引用:将clGraphs中的controller属性改为weak,防止视图控制器被意外保留导致内存泄漏。
  • 自动尺寸适配:设置autoresizingMask让vGraphs随父视图尺寸变化自动调整,保证绘图区域始终匹配容器。

内容的提问来源于stack exchange,提问作者Steve

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 11:45:22