波形图的性能优化

时间:2017-05-28 09:58:24

标签: ios swift uiscrollview drawing core-graphics

我正在构建一个绘制输入音频数据波形的应用程序。

以下是其外观的直观表示:

它的行为与Apple的原生VoiceMemos应用程序类似。但它缺乏性能。波形本身是一个UIScrollView子类,我在其中绘制CALayer的实例来表示紫色''并将它们添加为子图层。开始时波形为空,当声音输入开始时,我用此功能更新波形:

class ScrollingWaveformPlot: UIScrollView {

  var offset: CGFloat = 0
  var normalColor: UIColor?
  var waveforms: [CALayer] = []
  var lastBarRect: CGRect?
  var kBarWidth: Int = 5

  func updateGraph(with value: Float) {

    //Create instance
    self.lastBarRect = CGRect(x: self.offset,
                              y:   self.frame.height / 2,
                              width: CGFloat(self.barWidth),
                              height: -(CGFloat)(value * 2))


    let barLayer = CALayer()
    barLayer.bounds = self.lastBarRect!
    barLayer.position = CGPoint(x: self.offset + CGFloat(self.barWidth) / 2,
                                y: self.frame.height / 2)
    barLayer.backgroundColor = self.normalColor?.cgColor

    self.layer.addSublayer(barLayer)
    self.waveforms.append(barLayer)

    self.offset += 7

  }

...

}

当紫色条的最后一个矩形到达屏幕中间时,我开始增加波形的contentOffset.x以使其保持运行,就像Apple的VoiceMemos应用程序一样。

问题是:当条形数达到~500 ... 1000时,在setContentOffset期间开始出现一些明显的波形滞后。

self.inputAudioPlot.setContentOffset(CGPoint(x: CGFloat(self.offset) - CGFloat(self.view.frame.width / 2 - 7),y: 0), animated: false)

这里可以优化什么?任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:1)

只需删除从超级图层滚出屏幕的条形图。如果你想得到想象,你可以将它们放入队列中以便在添加新样本时重用,但这可能不值得付出努力。

如果您不让用户在该视图中滚动,则根本不值得使用滚动视图,而是在添加新视图时将可见条移动到左侧。

当然,如果您确实需要让用户滚动,您还有更多工作要做。然后,您首先必须存储您在某处显示的所有值,以便您可以将它们取回。使用此功能,您可以覆盖layoutSubviews以在滚动期间添加所有缺少的栏。

这基本上是UITableViewUICollectionView的工作原理,因此您可以使用集合视图和自定义布局来实现此功能。手动完成它可能会更容易,也可以更好地执行。

答案 1 :(得分:0)

我怀疑这可能是一个比你能承受的更大的重构,但SpriteKit可能会给你更好的性能并控制波形的渲染。

您可以使用SpiteNodes(比形状节点快得多)用于波形条。您只需移动包含所有这些精灵的父节点即可实现滚动。

Spritekit非常适合在渲染时跳过非可见节点,如果节点数量成为问题,您甚至可以从场景中动态删除/添加节点。