【问题标题】:I am able to draw on each ViewController to edit Original ImageView. Is there any way to fix this?我可以在每个 ViewController 上绘制来编辑原始 ImageView。有没有什么办法解决这一问题?
【发布时间】:2019-05-25 20:50:28
【问题描述】:

我正在开发一个动画应用程序,并且在其他 ViewController 中,我可以在原始 ImageView 上当前显示的图像上进行绘制。有没有办法解决这个问题?

这正是正在发生的事情。我真的不知道代码中的哪里存在问题。 https://drive.google.com/file/d/1M7qWKMugaqeDjGls3zvVitoRmwpOUJFY/view?usp=sharing

预计只能在 DrawingFrame ViewController 上绘制。但是,我可以在我的应用程序中绘制每个 ViewController

【问题讨论】:

    标签: xcode drawing cgcontext


    【解决方案1】:

    问题似乎是您的手势识别器仍在运行,即使您在当前视图之上呈现了另一个视图。

    这有点不寻常。通常,当您呈现这样的视图时,旧视图(及其手势识别器)将从视图层次结构中删除。我猜你只是将第二个视图滑到另一个上面。有几个解决方案:

    • 一种解决方案是确保定义这个新视图,以便 (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。

    上面应该只绘制drawingImageViewimage和从fromPointtoPoint的笔划。关于在“每个 ViewController”上绘图的问题在于其他地方。我们真的需要看看你呈现这个菜单场景的精确度。

    【讨论】:

    • 感谢您对我刚开始在 Xcode 中工作的糟糕编码实践感到抱歉。是的,问题仍然存在,我真的不明白发生了什么。我将 ImageView 中的图像存储到图像中,所以也许这就是它发生的地方......Idk......我可能只是使用 UIGraphicsImageRenderer 并希望它能解决我的问题。非常感谢您的帮助/提示。
    • 我发布了一个视频,希望能更清楚地了解正在发生的事情。我仍然不知道这个错误发生在哪里
    • 第二个有效(解决方案 B)!非常感谢。我没有手势识别器,这可能是我的问题之一。但我最终只是覆盖了每个 ViewController 中的每个 touchBegan、touchesEnded 等函数,并将不应该绘制的函数设置为什么都不返回。
    猜你喜欢
    • 1970-01-01
    • 2010-11-25
    • 2022-09-27
    • 1970-01-01
    • 2021-03-07
    • 1970-01-01
    • 2021-09-06
    • 2021-12-19
    相关资源
    最近更新 更多