Swift Drawing App是Laggy

时间:2017-05-02 01:08:05

标签: ios swift uiscrollview drawing lag

我目前正在制作绘图应用。我正在为iOS构建它,并且正在使用Swift 3这样做。

这只是一个基本的绘图应用程序,但我正在尝试添加一个额外的功能。我从一个UIScrollView开始,然后在该滚动视图中添加了一个图像视图。所有绘图部分都是使用图像视图完成的。首次启动应用程序时,滚动视图会完全放大。当您切换到“缩放模式”时,可以捏合缩放。问题是,当您第一次打开应用程序时,在放大时绘制时,绘图非常模糊。为了解决这个问题,我可以使用一行代码:

UIGraphicsBeginImageContextWithOptions((self.view.frame.size), false, 7.0)

这会导致绘图在放大时看起来很棒,但会导致应用程序运行非常迟缓。令我困惑的是,如果我将上面的代码更改为:

UIGraphicsBeginImageContextWithOptions((self.view.frame.size), false, 0.0)

并且一直缩小,绘图看起来完全一样(授予,我一直缩放)但它不再是滞后的。我知道这可能不是非常清楚,所以这是一个视频,显示第一个场景中发生的事情:https://youtu.be/E_9FKf1pUTY和第二个场景:https://youtu.be/OofFTS4Q0OA

所以基本上,我想知道是否有办法将放大的区域视为自己的视图。在我看来,好像应用程序正在更新整个图像视图,而不仅仅是在任何给定时间可见的部分。有没有办法只更新绘制的图像视图部分?对不起,如果这是一个令人困惑的帖子,如果有任何你不明白的事情,请随时提问。为了清楚起见,我将包括下面的所有绘图代码:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    print("Touches began")

    swiped = true

    if let touch = touches.first {
        lastPoint = touch.location(in: scrollView)
        lastPoint.x = lastPoint.x / scrollView.zoomScale
        lastPoint.y = lastPoint.y / scrollView.zoomScale
    }
}

func drawLines(fromPoint:CGPoint,toPoint:CGPoint) {
    print("\(fromPoint.x), \(fromPoint.y)")
    //UIGraphicsBeginImageContext(self.view.frame.size)
    UIGraphicsBeginImageContextWithOptions((scrollView.frame.size), false, 0.0)
    imageView.image?.draw(in: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
    let context = UIGraphicsGetCurrentContext()
    context?.move(to: CGPoint(x: fromPoint.x, y: fromPoint.y))
    context?.addLine(to: CGPoint(x: toPoint.x, y: toPoint.y))

    context?.setBlendMode(CGBlendMode.normal)
    context?.setLineCap(CGLineCap.round)
    if erase == true {
        context?.setLineWidth(30)
    }
    if erase == false {
        context?.setLineWidth(CGFloat(sizeVar))
    }
    if color == "black" {
        context?.setStrokeColor(UIColor.black.cgColor)
    }
    if color == "white" {
        context?.setStrokeColor(UIColor.white.cgColor)
    }
    if color == "blue" {
        context?.setStrokeColor(UIColor.blue.cgColor)
    }
    if color == "cyan" {
        context?.setStrokeColor(UIColor.cyan.cgColor)
    }
    if color == "green" {
        context?.setStrokeColor(UIColor.green.cgColor)
    }
    if color == "magenta" {
        context?.setStrokeColor(UIColor.magenta.cgColor)
    }
    if color == "red" {
        context?.setStrokeColor(UIColor.red.cgColor)
    }
    if color == "yellow" {
        context?.setStrokeColor(UIColor.yellow.cgColor)
    }

    context?.strokePath()

    imageView.image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {

    swiped = true

    if let touch = touches.first {
        var currentPoint = touch.location(in: scrollView)
        currentPoint.x = currentPoint.x / scrollView.zoomScale
        currentPoint.y = currentPoint.y / scrollView.zoomScale
        drawLines(fromPoint: lastPoint, toPoint: currentPoint)

        lastPoint = currentPoint
    }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    if !swiped {
        drawLines(fromPoint: lastPoint, toPoint: lastPoint)
    }
}

1 个答案:

答案 0 :(得分:0)

函数UIGraphicsBeginImageContextWithOptions(_:_:_:)中的scale参数不是质量设置,您不应该在其中放置任意值。这是一个比例因子,它类似于图像的@ 1x,@ 2x和@ 3x设置。它告诉系统在将图像像素映射到屏幕像素时使用的缩放因子。在大多数(几乎所有)情况下,你应该使用0,这意味着“使用屏幕的原生尺度”(@ 2x用于正常视网膜,或@ 3x用于iPhone 6+和7+。)你永远不应该将它设置为任意像7这样的值创建一个像往常一样7倍像素的图像,并强制系统每次都缩放它以进行画面绘制,这需要更多时间并且速度更慢。

接下来,为每个新行创建一个新图像是一种非常低效的绘图方式。它不断创建和释放大块内存,然后每次都必须完全重绘屏幕。相反,我会设置一个视图,它有一个CAShapeLayer作为它的支持层,并更新层中安装的路径。