调用setNeedsDisplay后drawRect函数未触发的绘图问题求助
问题分析与修复方案
核心问题
- vGraphs实例未加入视图层级:创建
vGraphs对象后未将其添加到graphCanvas的子视图中,系统无法触发它的draw(_:)方法。 - 绘图操作脱离绘制上下文:
plotGraph中的NSBezierPath绘制代码直接调用,此时无有效图形上下文(仅draw(_:)执行时系统才会提供上下文),导致抛出invalid context错误。 - 类名不符合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
相关产品推荐
相关产品推荐

