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

如何清空UIView?iOS绘图应用画布清空实现方案

实现绘图视图的一键清空功能

嘿,我看了你的绘图代码和需求,这里帮你调整一下,确保清空按钮能正常工作,同时修正几个小问题让代码更规范易读:

先说说现有代码里的小问题

  • 拼写错误:比如storkes应该是strokes,类名subClassOFUIVIEW不符合Swift的驼峰命名规范
  • IBOutlet绑定错误:@IBOutlet weak var jj: draw!里的draw应该是你的绘图视图类drawViewSwift(我后面统一改成更规范的DrawViewSwift)
  • clear()方法的实现有点绕,其实可以更直接,不需要额外的clearing标记

修正后的完整实现

1. 基础视图类(修正命名)

import UIKit

// 用驼峰式命名更符合Swift规范
class DrawViewBase: UIView {
    override func awakeFromNib() {
        super.awakeFromNib()
        layer.shadowOpacity = 1
        layer.shadowOffset = CGSize(width: 1, height: 1)
        layer.shadowPath = CGPath(rect: bounds, transform: nil)
    }
}

2. 核心绘图视图类

import UIKit

// 结构体名同样用大驼峰
struct Stroke {
    let startPoint: CGPoint
    let endPoint: CGPoint
    let color: CGColor
}

class DrawViewSwift: DrawViewBase {
    var isDrawing = false
    var lastPoint: CGPoint? // 改成可选值,避免强制解包崩溃
    var strokeColor: CGColor = UIColor.black.cgColor
    var strokes = [Stroke]() // 修正拼写错误
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard !isDrawing else { return }
        isDrawing = true
        
        guard let touch = touches.first else { return }
        lastPoint = touch.location(in: self)
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard isDrawing, let touch = touches.first, let lastPoint = lastPoint else { return }
        
        let currentPoint = touch.location(in: self)
        let newStroke = Stroke(startPoint: lastPoint, endPoint: currentPoint, color: strokeColor)
        strokes.append(newStroke)
        
        self.lastPoint = currentPoint
        setNeedsDisplay() // 每次移动都触发重绘,实时显示路径
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard isDrawing, let touch = touches.first, let lastPoint = lastPoint else { return }
        isDrawing = false
        
        let currentPoint = touch.location(in: self)
        let newStroke = Stroke(startPoint: lastPoint, endPoint: currentPoint, color: strokeColor)
        strokes.append(newStroke)
        
        self.lastPoint = nil
        setNeedsDisplay()
    }
    
    // 这就是清空画布的核心方法
    func clearCanvas() {
        strokes.removeAll() // 清空所有绘制路径
        setNeedsDisplay() // 触发重绘,画布就变成空白了
    }
    
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        
        guard let context = UIGraphicsGetCurrentContext() else { return }
        
        context.setLineWidth(10)
        context.setLineCap(.round)
        
        // 遍历所有路径绘制
        for stroke in strokes {
            context.beginPath()
            context.move(to: stroke.startPoint)
            context.addLine(to: stroke.endPoint)
            context.setStrokeColor(stroke.color)
            context.strokePath()
        }
    }
}

3. 视图控制器的两种实现方式

方式一:用Storyboard绑定视图和按钮

如果你是用Storyboard搭建界面,这样写:

import UIKit

class ViewController: UIViewController {
    // 在Storyboard里把你的绘图视图绑定到这个IBOutlet
    @IBOutlet weak var drawView: DrawViewSwift!
    
    // 清空按钮的点击事件(Storyboard里绑定这个方法)
    @IBAction func clearButtonTapped(_ sender: UIButton) {
        drawView.clearCanvas()
    }
}

方式二:纯代码创建视图(和你原来的MyViewController对应)

import UIKit

class MyViewController: UIViewController {
    override func loadView() {
        let drawView = DrawViewSwift()
        drawView.backgroundColor = .white
        
        // 创建清空按钮,调整位置让它更合理
        let clearButton = UIButton(type: .system)
        clearButton.setTitle("清空画布", for: .normal)
        clearButton.frame = CGRect(x: 50, y: UIScreen.main.bounds.height - 120, width: UIScreen.main.bounds.width - 100, height: 44)
        clearButton.addTarget(self, action: #selector(handleClearTap), for: .touchUpInside)
        
        drawView.addSubview(clearButton)
        self.view = drawView
    }
    
    @objc private func handleClearTap() {
        (view as? DrawViewSwift)?.clearCanvas()
    }
}

关键逻辑解释

  • 清空原理:我们所有的绘制路径都存在strokes数组里,draw(_:)方法会根据这个数组的内容来绘制图形。所以只要清空数组再调用setNeedsDisplay(),视图重绘时就没有路径可以画,自然就变成空白画布了。
  • 可选值优化:把lastPoint改成可选值,避免了强制解包可能导致的崩溃,代码更安全。
  • 命名规范:Swift里类、结构体用大驼峰,变量用小驼峰,这样团队协作或者自己后期维护时更容易读懂代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:15:39