PencilKit自定义套索工具移动多PKStroke卡顿,求优化方案
解决PencilKit多笔画移动卡顿问题的优化方案
问题根源
你当前的实现每次移动单个笔画时都会修改canvas.drawing,每修改一次就会触发一次canvasViewDrawingDidChange回调,多个笔画时会重复触发视图刷新与重绘,这是卡顿的核心原因。此外直接设置transform的方式还存在位移无法累加的逻辑问题(拖动多次会出现跳变)。
优化方案
1. 批量更新绘图,减少刷新次数
PKDrawing是值类型,每次修改单个笔画都会生成新的PKDrawing实例。改为先创建绘图副本,批量修改所有选中笔画后一次性赋值给画布,这样只会触发一次视图刷新。
2. 保存初始变换,正确累加位移
维护选中笔画的初始transform,确保每次拖动的位移是基于原始位置的累加,避免transform被反复重置导致的跳变问题。
3. 优化选中逻辑(提升选中效率)
先通过笔画的boundingBox快速过滤与选中矩形无交集的笔画,减少不必要的点遍历操作。
完整优化代码
新增状态变量
// 存储选中笔画的索引 private var selected: [Int] = [] // 记录选中笔画的初始transform,用于计算累加位移 private var originalStrokeTransforms: [Int: CGAffineTransform] = [:] // 记录当前拖动的总位移 private var totalDragOffset: CGSize = .zero
优化选中函数
func select(rect: CGRect) { selected.removeAll() originalStrokeTransforms.removeAll() let selectionPath = UIBezierPath(roundedRect: rect, cornerRadius: 5) for (index, stroke) in canvas.drawing.strokes.enumerated() { // 先通过boundingBox快速过滤,跳过完全不在选中区域的笔画 let transformedStrokeBounds = stroke.boundingBox.applying(stroke.transform) guard rect.intersects(transformedStrokeBounds) else { continue } // 再检查笔画路径点是否在选中区域内 for point in stroke.path { if selectionPath.contains(point.location) { selected.append(index) originalStrokeTransforms[index] = stroke.transform break } } } // 重置拖动位移 totalDragOffset = .zero }
优化移动函数
func moveSelected(with delta: CGSize) { // 累加本次拖动的位移 totalDragOffset.width += delta.width totalDragOffset.height += delta.height // 创建绘图副本,批量修改选中笔画 var updatedStrokes = canvas.drawing.strokes for index in selected { guard let originalTransform = originalStrokeTransforms[index] else { continue } // 基于初始transform叠加总位移 let newTransform = originalTransform.concatenating( CGAffineTransform(translationX: totalDragOffset.width, y: totalDragOffset.height) ) updatedStrokes[index].transform = newTransform } // 一次性更新画布,仅触发一次视图刷新 canvas.drawing = PKDrawing(strokes: updatedStrokes) }
额外优化建议
- 在
canvasViewDrawingDidChange回调中,避免执行不必要的耗时操作,比如在拖动过程中可以跳过数据持久化等逻辑,仅在拖动结束后执行。 - 如果选中区域较大,可考虑异步执行选中逻辑,避免阻塞主线程。
内容的提问来源于stack exchange,提问作者jakob witsch
相关产品推荐
相关产品推荐

