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

Swift绘图应用开发:实现图片数组存储与撤销按钮功能

实现绘图应用的撤销功能

嗨,我来帮你搞定这个撤销按钮的实现!你的代码已经完成了绘图的核心逻辑,现在只需要添加历史状态保存和撤销恢复的逻辑就可以了,步骤很清晰:

1. 添加历史记录数组

首先在你的ViewController类里,添加一个用来保存绘图历史状态的数组,每完成一笔绘制,我们就把当前的绘图状态存进去:

// 保存每一步绘图完成后的状态,用于撤销操作
private var drawingHistory: [UIImage] = []

2. 保存绘图状态到历史记录

修改你的touchesEnded方法,在把临时图层(tempImageView)合并到主图层(mainImageView)之前,先把当前主图层的状态存入历史数组——这样每完成一笔,我们就有了撤销的依据:

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    if !swiped {
        // draw a single point
        drawLineFrom(fromPoint: lastPoint, toPoint: lastPoint)
    }
    
    // ✅ 新增:合并前保存当前主图层的状态到历史记录
    if let currentMainImage = mainImageView.image {
        drawingHistory.append(currentMainImage)
    }

    // Merge tempImageView into mainImageView
    UIGraphicsBeginImageContext(mainImageView.frame.size)
    mainImageView.image?.draw(in: CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height),blendMode: CGBlendMode.normal, alpha: 1.0)
    tempImageView.image?.draw(in: CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height), blendMode: CGBlendMode.normal, alpha: opacity)
    mainImageView.image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    
    tempImageView.image = nil
    floaty.isHidden = false
    postBtn.isHidden = false
    resetBtn.isHidden = false
    undoBtn.isHidden = false
    dismissBtn.isHidden = false
}

3. 实现撤销按钮的点击逻辑

给你的撤销按钮(undoBtn)添加点击事件方法,逻辑很简单:检查历史数组是否有内容,如果有,就取出最后一个状态恢复到主图层,同时从数组里移除这个状态(因为已经撤销了):

@IBAction func undoButtonTapped(_ sender: UIButton) {
    // 没有历史记录就直接返回,避免崩溃
    guard !drawingHistory.isEmpty else {
        // 这里可以加个提示,比如"没有可撤销的操作"
        return
    }
    
    // 取出最后一次的绘图状态并恢复
    let lastDrawingState = drawingHistory.removeLast()
    mainImageView.image = lastDrawingState
    // 清空临时图层,避免残留的绘制痕迹
    tempImageView.image = nil
}

4. 重置功能的配套修改

别忘了给你的重置按钮(resetBtn)也加个逻辑,清空历史数组,不然重置后历史记录还在会导致奇怪的问题:

@IBAction func resetButtonTapped(_ sender: UIButton) {
    mainImageView.image = nil
    tempImageView.image = nil
    // ✅ 清空历史记录
    drawingHistory.removeAll()
    // 其他你原本的重置逻辑...
}

注意事项

  • 这个方案是基于**每完成一笔(touchesEnded)**保存一次状态,如果你需要更精细的撤销(比如每移动一次手指就保存),可以调整保存时机,但这样会增加内存占用,一般一笔一存足够用了。
  • 如果你的绘图应用会处理超大尺寸的图片,历史数组可能会占用较多内存,这时候可以考虑用磁盘缓存代替内存数组,但对于普通的绘图场景,内存数组完全够用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:00:54