2017-05-28 73 views
2

我正在構建一個繪製輸入音頻數據波形的應用程序。波形圖的性能優化

這裏是它的外觀的可視化表示:

其作用類似的方式來蘋果原生應用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以保持其運行像蘋果的VoiceMemos應用程序。

問題是:當條數達到〜500 ... 1000時,一些明顯的波形滯後在setContentOffset期間開始發生。

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

什麼在這裏可以優化?任何幫助讚賞。

+0

您正在添加子視圖_ad infinitum_?如果是這樣,你需要使用'UICollectionView'來實現這個功能,以便重用你的視圖 –

回答

1

只需從超級圖層中刪除滾動到屏幕外的條形圖。如果你想變得有趣,可以在添加新樣本時將它們放入隊列中重用,但這可能不值得。

如果您不讓用戶在該視圖內滾動,則可能根本不值得使用滾動視圖,而是在添加新視圖時向左移動可見條。

當然,如果你確實需要讓用戶滾動,你還有更多的工作要做。然後,您首先必須存儲您在某處顯示的所有值,以便將它們還原。使用此功能,您可以覆蓋layoutSubviews以在滾動期間添加所有缺失的條。

這基本上是如何工作的UITableViewUICollectionView,所以你可能能夠使用集合視圖和自定義佈局來實現這一點。儘管手動執行操作可能會更容易,而且執行也會更好一些。

+0

謝謝你的回答。如何在滾動和重寫'layoutSubviews'期間添加視圖,你有任何可行的來源嗎?對我來說這是一種神祕感。 –

0

我懷疑這可能是一個更大的重構比你能負擔得起,但SpriteKit可能會給你更好的性能和控制波形的渲染。

您可以對波形條使用SpiteNodes(它比形狀節點快得多)。您可以通過僅移動包含所有這些精靈的父節點來實現滾動。

Spritekit在渲染時非常擅長跳過不可見的節點,並且如果節點數量成爲問題,甚至可以動態地從場景中刪除/添加節點。