简体   繁体   English

在Swift中不断显示动画

[英]Constantly animated view in Swift

I'm creating a subclass of AVPlayerController , that observes the player and handles player's states. 我正在创建AVPlayerController的子类,该子类观察玩家并处理玩家的状态。 If AVPlayerItemStatus is .failed , I add a custom UIView over the player's frame. 如果AVPlayerItemStatus.failed ,则在播放器框架上添加自定义UIView At present, the important parts of my custom view's code looks like this: 目前,我的自定义视图代码的重要部分如下所示:

class NoiseView: UIView {

    ...

    var timer: Timer?
    func animate() {
        timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)
    }

    func stopAnimating() {
        timer?.invalidate()
    }

    @objc func timerAction() {
        self.setNeedsDisplay()
    }

    override func draw(_ rect: CGRect) {
        super.draw(rect)
        let context = UIGraphicsGetCurrentContext()!
        let h = rect.height
        let w = rect.width

        var val: CGFloat!
        var color: UIColor!

        for i in 0...Int(w-1) {
            for j in 0...Int(h-1) {
                val = .random
                color = UIColor(red: val, green: val, blue: val, alpha: 1.0)

                context.setFillColor(color.cgColor)
                context.fill(CGRect(x: i, y: j, width: 1, height: 1))
            }
        }

        context.flush()
    } 
}

I'm calling the method animate() from other ViewController that keeps the NoiseView object. 我正在从其他ViewController NoiseView对象的ViewController调用方法animate()

The thing is, it's working as it's supposed to work (view is animating and creating a white noise) but the app starts to work slowly. 事实是,它正在按预期的方式工作(视图正在设置动画并产生白噪声),但应用程序开始缓慢运行。 What should be a proper approach to redraw the view without causing such a performance drop? 在不导致性能下降的情况下重新绘制视图的正确方法是什么?

By the way, the drop happened with 0.1s interval (10 FPS). 顺便说一下,下降发生的间隔为0.1s(10 FPS)。 What I want to accomplish is having a constant white noise with at least 30 FPS to look like a legit tv noise. 我要完成的工作是保持恒定的白噪声(至少30 FPS),看起来像合法的电视噪声。

Instead of using the timer and calling setNeedsDisplay which in result will keep calling draw method, hence slowing the app. 而不是使用计时器并调用setNeedsDisplay,结果是将继续调用draw方法,从而降低了应用程序的速度。

Use CAAnimation and create CALayer or CAreplicator layer and animate that. 使用CAAnimation并创建CALayer或CAreplicator层并对其进行动画处理。

If you need code you can check this link Color Picker or I can post some demo code after sometime, Its fifa time :-p. 如果您需要代码,可以检查此链接“ 拾色器”,或者我可以在一段时间后发布一些演示代码,它的FIFA时间:-p。

CAReplicatorlayer CALayer CAReplicatorlayer CALayer

There are a number of strategies you can try to optimize the drawing code, but to me the most obvious one is that you should pre-calculate the CGRects you need outside the drawing code. 您可以尝试多种策略来优化绘图代码,但对我而言,最明显的策略是,应在绘图代码之外预先计算所需的CGRect。

The loops you're running require w^h iterations for each frame of animation to calculate all the CGRects you need. 您正在运行的循环需要对动画的每一帧进行w ^ h次迭代才能计算出所需的所有CGRect。 That's a lot, and totally unnecessary, because the CGRects will always be the same so long as the width and height are unchanged. 这很多,而且完全没有必要,因为只要宽度和高度不变,CGRect就会始终相同。 Instead, you should do something like this: 相反,您应该执行以下操作:

var cachedRects = [CGRect]()
override var frame: CGRect {
    didSet {
        calculateRects()
    }
}

func calculateRects() {
    cachedRects = []
    let w = frame.width
    let h = frame.height
    for i in 0...Int(w-1) {
        for j in 0...Int(h-1) {
            let rect = CGRect(x: i, y: j, width: 1, height: 1)
            cachedRects += [rect]
        }
    }
}

override func draw(_ rect: CGRect) {
    super.draw(rect)
    let context = UIGraphicsGetCurrentContext()!
    var val: CGFloat!
    var color: UIColor!
    for rect in cachedRects {
        val = .random
        color = UIColor(red: val, green: val, blue: val, alpha: 1.0)
        context.setFillColor(color.cgColor)
        context.fill(rect)
    }
    context.flush()
}

By pre-caching the rects, you only have to do (w * h) number of iterations, which is a vast improvement. 通过预缓存rect,您只需要做(w * h)次迭代,这是一个很大的改进。

If that isn't enough to improve performance, you can further optimize using similar pre-caching strategies, like instead of randomizing the each pixel, pre-calculate tiles of random colors outside the draw code, and then randomly assemble them in drawRect() . 如果这还不足以提高性能,则可以使用类似的预缓存策略进一步优化,例如代替随机化每个像素,在绘图代码之外预先计算随机颜色的图块,然后在drawRect()随机组合它们。 If the randomizer is what's the performance problem, this would cut down on the amount of work it would have to. 如果随机化器是性能问题所在,那么它将减少所需的工作量。

The key strategy is to try and minimize the amount of work your drawRect() method has to do, because it run on each frame of animation. 关键策略是尝试并尽量减少drawRect()方法必须完成的工作量,因为它运行在动画的每一帧上。

Good luck! 祝好运!

Custom draw(rect:) methods can cause performance hits. 自定义draw(rect:)方法可能会导致性能下降。

I suggest looking into adding a CAAnimation or CAAnimationGroup to your white noise view. 我建议您考虑将CAAnimationCAAnimationGroup添加到白噪声视图。

CABasicAnimation Documentation CABasicAnimation文档

CAAnimationGroup StackOverflow Post CAAnimationGroup StackOverflow帖子

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM