[英]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。
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. 我建议您考虑将
CAAnimation
或CAAnimationGroup
添加到白噪声视图。
CABasicAnimation Documentation CABasicAnimation文档
CAAnimationGroup StackOverflow Post CAAnimationGroup StackOverflow帖子
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.