我目前正在开发一个绘图应用程序。我正在为 iOS 构建它,并使用 Swift 3 来实现。
这只是一个基本的绘图应用程序,但我正在尝试添加一个额外的功能。我从 UIScrollView 开始,然后向该 ScrollView 添加了一个 ImageView 。所有绘图部分都是通过 ImageView 完成的。当您第一次启动应用程序时, ScrollView 会完全放大。当您切换到“缩放模式”时,您可以通过捏合来缩放。问题是,当你第一次打开应用程序时,当你放大绘图时,绘图非常模糊。为了解决这个问题,我可以使用如下代码:
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
所以基本上,我想知道是否有一种方法可以将放大的区域视为它自己的 View 。在我看来,应用程序似乎正在更新整个 ImageView ,而不仅仅是在任何给定时间可见的部分。有没有办法只更新绘制的 ImageView 部分?抱歉,如果这篇文章有点令人困惑,如果有任何不明白的地方,请随时提问。为了清楚起见,我将包含以下所有绘图代码:
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)
}
}
最佳答案
函数 UIGraphicsBeginImageContextWithOptions(_:_:_:)
中的比例参数不是质量设置,您不应在其中放置任意值。它是一个比例因子,类似于图像的 @1x、@2x 和 @3x 设置。它告诉系统将图像像素映射到屏幕像素时要使用的缩放因子。在大多数(几乎所有)情况下,您应该使用 0,这意味着“使用屏幕的原始比例”(@2x 表示正常视网膜,或 @3x 表示 iPhone 6+ 和 7+。)您永远不应该将其设置为任意值例如 7 之类的值。这将创建一个像素数为正常像素数 7 倍的图像,并强制系统每次都对其进行缩放以进行屏幕绘制,这会花费更多时间且速度更慢。
接下来,为每条新线创建一个新图像是一种极其低效的绘图方式。它不断地创建和释放大块内存,然后每次都必须完全重绘屏幕。相反,我会设置一个具有 CAShapeLayer
作为支持层的 View ,并更新安装在该层中的路径。
关于ios - Swift 绘图应用程序很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43728607/