【问题标题】:iOS CGContext Poor PerformanceiOS CGContext 性能不佳
【发布时间】:2016-11-21 01:56:04
【问题描述】:

我编写了一个每 1/60 秒调用一次的渲染函数。如下图所示。本质上,它以使用正弦的放射状图案呈现 40 条线。看起来像这样http://imgur.com/a/kPKtT。当我在我的 iPhone 6s 上运行它并打开调试器时,它显示它使用了大约 60% 的 CPU,并且它只是使“高”电池使用水平。这对我来说似乎不对,只有 40 条简单的行对吗?

我可以更有效地执行此操作吗?我是否应该尝试使用 CALayer 或 Metal 之类的其他东西来获得更好的性能?顺便说一句,我对此很陌生。

func render() { tick += 0.01
    let renderer = UIGraphicsImageRenderer(size: CGSize(width: 375, height: 667))
    let img = renderer.image { ctx in
        let c = ctx.cgContext

        // Set background
        let background = CGRect(x: 0, y: 0, width: 375, height: 667)
        c.setFillColor(UIColor.black.cgColor)
        c.addRect(background)
        c.drawPath(using: .fillStroke)

        // Function to draw a line
        func line(p1:CGPoint, p2:CGPoint) {
            let line = CGRect(x: 0, y: 0, width: 200, height: 200)
            c.addLines(between: [p1,p2])
            c.drawPath(using: .fillStroke)
        }

        // Draw lines
        c.setStrokeColor(UIColor.white.cgColor)
        c.setLineWidth(1)
        c.setLineCap(CGLineCap.round)
        for i in 0...39 {
            let n:CGFloat = CGFloat(i) * CGFloat.pi/40
            let d:CGFloat = sin(tick + CGFloat(i)*CGFloat.pi/5)*20 + 100
            line(p1: CGPoint(x: d*cos(tick+n)+187.5,            y: d*sin(tick+n)+333.5),
                 p2: CGPoint(x: d*cos(tick+n+CGFloat.pi)+187.5, y: d*sin(tick+n+CGFloat.pi)+333.5))
        }   
    }
    imageView.image = img
}

【问题讨论】:

  • while true { print("loop" } 应该很快,只有 1 行,对吧?
  • 应该可能使用scenekit/gamekit或openGL来做这件事,我不认为UIGraphicsImageRenderer被设计成这样使用
  • 您每秒调用cos 2400 次和每秒调用sin 3600 次,并且每秒至少执行16800 次乘法运算,所有这些都在for 循环内。
  • 您的形状围绕 4 个轴对称。您可以以昂贵的方式计算 40 条线中的 6 条线的坐标,并通过涉及非常简单数学的简单反射绘制其他 34 条线。
  • @rmaddy 感谢您提供有趣的解释。我尝试删除代码的某些部分,例如正弦或乘法,看看它是否有帮助。我最终删除了整个 for 循环,所以它只是每 1/60 秒绘制的黑色方块。即使只有黑色背景,它仍然使用超过 50% 的 CPU。我想我会尝试使用 OpenGL 或 Metal...

标签: ios swift performance cgcontext


【解决方案1】:

我认为 apptoach 不好。当您想要显示动画内容时,您不应该重绘视图。您应该使用 CoreAnimation。好消息是它易于实施。坏消息是它需要一点学习。 ;)

对您的代码的一些建议:

  1. 绘图的某些部分似乎是恒定的。因此,不要一次又一次地重绘这个。相反,您可以将其放在单独的层中。
  2. 正如@rmaddy 建议的那样,您需要许多sincos 计算。但这些值应该始终相同。因此,您可以计算一次并缓存它们。
  3. 您可以在draw(in:) 中实现绘图,并对代码的所有可变部分使用动态属性。您可以使用 CoreAnimation 中的动画,然后为您的绘图设置动画。在 Swift 中创建动态 CA 属性有点棘手。 (据我所知,您必须使用 @NSManaged(!) 注释它们,并且您必须覆盖 needsDisplay(forKey:) 并为它们返回 true。)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-04
    • 2011-01-03
    相关资源
    最近更新 更多