问题似乎是您的手势识别器仍在运行,即使您在当前视图之上呈现了另一个视图。
这有点不寻常。通常,当您呈现这样的视图时,旧视图(及其手势识别器)将从视图层次结构中删除。我猜你只是将第二个视图滑到另一个上面。有几个解决方案:
一种解决方案是确保定义这个新视图,以便 (a) 它接受用户交互; (b) 编写代码以处理这些手势。这样可以避免背后的视图拾取这些手势。
另一种解决方案是在显示菜单视图时禁用手势识别器识别器,并在关闭菜单时重新启用它。
第三种解决方案是更改显示该菜单视图的方式,确保在执行此操作时从视图层次结构中删除当前视图。不过,标准的show/present 转换通常会执行此操作,因此我们可能需要查看您如何呈现此菜单视图以进一步评论。
话虽如此,一些不相关的观察:
你应该使用UIGraphicsBeginImageContextWithOptions而不是UIGraphicsBeginImageContext;
-
而不是
if pencil.eraser == true { ... }
你可以
if pencil.eraser { ... }
-
我建议给 pencil 一个计算属性:
var color: UIColor { return UIColor(red: red, green: green, blue: blue, alpha: opacity) }
那你可以参考pencil.color;
属性名称应以小写字母开头;和
drawingFrame 是一个令人困惑的名称,恕我直言,因为它不是“框架”,而很可能是 UIImageView。我会称它为drawingImageView 或类似的名称。
产量:
func drawLine(from fromPoint: CGPoint, to toPoint: CGPoint) {
guard let pencil = pencil else { return }
//begins current context (and defer the ending of the context)
UIGraphicsBeginImageContextWithOptions(drawingImageView.bounds.size, false, 0)
defer { UIGraphicsEndImageContext() }
//where to draw
drawingImageView.image?.draw(in: drawingImageView.bounds)
//saves context
guard let context = UIGraphicsGetCurrentContext() else { return }
//drawing the line
context.move(to: fromPoint)
context.addLine(to: toPoint)
context.setLineCap(.round)
if pencil.eraser {
//Eraser
context.setBlendMode(.clear)
context.setLineWidth(10)
context.setStrokeColor(UIColor.white.cgColor)
} else {
//opacity, brush width, etc.
context.setBlendMode(.normal)
context.setLineWidth(pencil.pencilWidth)
context.setStrokeColor(pencil.color.cgColor)
}
context.strokePath()
//storing context back into the imageView
drawingImageView.image = UIGraphicsGetImageFromCurrentImageContext()
}
或者,更好的是,完全退休 UIGraphicsBeginImageContext 并使用现代的 UIGraphicsImageRenderer:
func drawLine(from fromPoint: CGPoint, to toPoint: CGPoint) {
guard let pencil = pencil else { return }
drawingImageView.image = UIGraphicsImageRenderer(size: drawingImageView.bounds.size).image { _ in
drawingImageView.image?.draw(in: drawingImageView.bounds)
let path = UIBezierPath()
path.move(to: fromPoint)
path.addLine(to: toPoint)
path.lineCapStyle = .round
if pencil.eraser {
path.lineWidth = 10
UIColor.white.setStroke()
} else {
path.lineWidth = pencil.pencilWidth
pencil.color.setStroke()
}
path.stroke()
}
}
有关 UIGraphicsImageRenderer 的更多信息,请参阅 WWDC 2018 Image and Graphics Best Practices 的“屏幕外绘图”部分。
顺便说一句,一旦你解决了这个问题,你可能想重新审视这个“从 a 点到 b 点的笔划并重新快照”的逻辑来捕获一个点数组并从整个系列中构建一条路径,并且不要重新快照任何点,但只有在添加了一大堆之后。这个快照过程很慢,你会发现用户体验比它需要的多一点。我个人在 100 点左右后重新快照(此时重新绘制整个路径的时间足够慢,它并不比快照过程快多少,所以如果我快照并从我离开的地方重新启动路径,然后它再次加速)。
但你说:
预计只能在 DrawingFrame ViewController 上绘制。但是,我可以在我的应用程序中绘制每个 ViewController。
上面应该只绘制drawingImageView的image和从fromPoint到toPoint的笔划。关于在“每个 ViewController”上绘图的问题在于其他地方。我们真的需要看看你呈现这个菜单场景的精确度。