我正在创建 AVPlayerController
的子类,它观察播放器并处理播放器的状态。如果 AVPlayerItemStatus
是 .failed
,我会在播放器的框架上添加一个自定义的 UIView
。目前,我的自定义 View 代码的重要部分如下所示:
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()
}
}
我正在从保留 NoiseView
对象的其他 ViewController
调用方法 animate()
。
问题是,它按预期工作( View 正在动画并产生白噪声)但应用程序开始运行缓慢。在不导致此类性能下降的情况下重绘 View 的正确方法应该是什么?
顺便说一句,下降发生在 0.1s 间隔(10 FPS)。我想要完成的是拥有至少 30 FPS 的恒定白噪声,看起来像合法的电视噪声。
最佳答案
您可以尝试多种策略来优化绘图代码,但对我来说最明显的一个是您应该在绘图代码之外预先计算您需要的 CGRects。
您正在运行的循环需要对每个动画帧 进行 w^h 次迭代,以计算您需要的所有 CGRect。这很多,而且完全没有必要,因为只要宽度和高度不变,CGRects 就会始终相同。相反,您应该这样做:
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()
}
通过预缓存 rects,您只需执行 (w * h) 次迭代,这是一个巨大的改进。
如果这还不足以提高性能,您可以使用类似的预缓存策略进一步优化,例如不是随机化每个像素,而是在绘制代码之外预先计算随机颜色的图 block ,然后将它们随机组合到drawRect()
。如果随机发生器是性能问题所在,这将减少它必须要做的工作量。
关键策略是尽量减少 drawRect()
方法必须完成的工作量,因为它在每一帧动画上运行。
祝你好运!
关于ios - Swift 中的持续动画 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51159813/