我能够在每个ViewController上进行绘制以编辑原始ImageView。有没有什么办法解决这一问题?

时间:2019-05-25 20:50:28

标签: xcode drawing cgcontext

我正在开发一个动画应用程序,并且彼此之间可以在ViewController中绘制原始ImageView上当前显示的图像。有什么办法可以解决这个问题?

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

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

1 个答案:

答案 0 :(得分:0)

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

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

  • 一种解决方案是确保定义此新视图,以便(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并重新快照”的逻辑,以捕获点阵列并从整个系列中构建路径,并且不要再快照任何点,只有在添加了一大堆之后才可以。这个快照过程很慢,您会发现UX的结结超出了它的需要。我个人在大约100点后重新快照(此时重新快照整个路径的时间足够慢,因此它不比快照过程快很多,因此,如果我快照并从上次中断的地方重新开始,然后它又加快了速度。)

但是你说:

  

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

以上内容仅应绘制image中的drawingImageView以及从fromPointtoPoint的笔划。关于使用“每个ViewController”绘制的问题都在其他地方。我们确实需要查看您呈现此菜单场景的精确度。