Xcode Instrument中SCNNode上SCNAudioPlayer的持久性

时间:2018-07-19 20:51:21

标签: ios swift instruments scnnode

我创建了SCNNode的子类。它由几个子节点组成。 我已经声明了一种方法,即。 soundCasual()SCNAudioPlayer添加到此类的实例。调用此方法时,一切都按预期工作并且正在播放音频。每当该节点被点击(手势)时,就会在该节点上调用此方法。

代码:

class MyNode: SCNNode {
    let wrapperNode = SCNNode()
    let audioSource5 = SCNAudioSource(fileNamed: "audiofile.mp3")

    override init() {
        super.init()

        if let virtualScene = SCNScene(named: "MyNode.scn", inDirectory: "Assets.scnassets/Shapes/MyNode") {
            for child in virtualScene.rootNode.childNodes {
                wrapperNode.addChildNode(child)
            }
        }
    }

   func soundCasual() {
        DispatchQueue.global(qos: .userInteractive).async { [weak self] in
            if let audioSource = self?.audioSource5 {
                let audioPlayer = SCNAudioPlayer(source: audioSource)
                self?.wrapperNode.removeAllAudioPlayers()
                self?.wrapperNode.addAudioPlayer(audioPlayer)
            }
        }
    }
}

仪器内的问题(分配)

当我分析整个代码库(还有其他几件事)时,我发现只要在该节点上点击,在Instruments中进行性能分析时,SCNAudioPlayer的分配计数就会增加一。但是所有增加都是持续。根据{{​​1}}的定义,我假设播放器在播放后被删除了,这就是为什么增量应该在瞬时分配中的原因,但是它不能像这样工作。这就是为什么我在将SCNAudioPlayer添加到节点之前尝试SCNAudioPlayer的原因,如您在removeAllAudioPlayers()的代码中所见。但是问题仍然存在。

直到拍摄此快照为止,我在该节点上轻击了 17 次,并且还针对SCNAudioPlayer的持久分配显示了17个。

注意 soundCasual()应该是10,因为我正在应用中使用10个音频源

enter image description here

这对于我的应用程序中的所有其他SCNNode都是如此。 请帮助,因为我无法理解我到底想念什么。

编辑

按照建议,我将SCNAudioSource更改为

init()

尽管如此,“乐器”中的分配将audioPlayers显示为持久性的。尽管在检查let path = Bundle.main.path(forResource: "Keemo", ofType: "scn", inDirectory: "Assets.scnassets/Shapes/Keemo") if let path = path , let keemo = SCNReferenceNode(url: URL(fileURLWithPath: path)) { keemo.load() } func soundPlay() { DispatchQueue.global(qos: .userInteractive).async { [weak self] in if let audioSource = self?.audioSourcePlay { audioSource.volume = 0.1 let audioPlayer = SCNAudioPlayer(source: audioSource) self?.removeAllAudioPlayers() self?.addAudioPlayer(audioPlayer) } } } 时它表明在某一点上仅附加了一个audioPlayer节点。

编辑

即使在简单情况下,当我使用默认情况下在XCode中创建的Scenekit应用程序中附加的样板代码库时,也会出现此问题。因此,此问题已作为Apple的错误提出。 https://bugreport.apple.com/web/?problemID=43482539

WORKAROUND

我使用的是AVAudioPlayer而不是SCNAudioPlayer,但不完全相同,但是至少这种方式的内存不会导致崩溃。

2 个答案:

答案 0 :(得分:1)

我对SceneKit不熟悉,但是根据我对UIKit和SpriteKit的经验,我怀疑您对wrapperNodevirtualScene的使用会弄乱垃圾收集器。

我会尝试删除wrapperNode并将所有内容添加到self(因为selfSCNNode)。

您的场景中使用了哪个节点? self还是wrapperNode?并且您的示例代码wrapperNode并未添加到self中,因此它实际上可能不是场景的一部分。

此外,您可能应该使用SCNReferenceNode而不是使用的虚拟场景。

!!!此代码未经测试!!!

class MyNode: SCNReferenceNode {
    let audioSource5 = SCNAudioSource(fileNamed: "audiofile.mp3")

    func soundCasual() {
        DispatchQueue.global(qos: .userInteractive).async { [weak self] in
            if let audioSource = self?.audioSource5 {
                let audioPlayer = SCNAudioPlayer(source: audioSource)
                self?.removeAllAudioPlayers()
                self?.addAudioPlayer(audioPlayer)
            }
        }
    }
}


// If you programmatically create this node, you'll have to call .load() on it
let referenceNode = SCNReferenceNode(URL: referenceURL)
referenceNode.load()

HtH!

答案 1 :(得分:0)

如果尚未找到答案,则需要在节点完成播放后从节点中删除SCNAudioPlayer:

if let audioSource = self?.audioSourcePlay {
    audioSource.volume = 0.1
    let audioPlayer = SCNAudioPlayer(source: audioSource)
    self?.removeAllAudioPlayers()
    self?.addAudioPlayer(audioPlayer)
    self?.audioplayer.didFinishPlayback = {
        self?.removeAudioPlayer(audioPlayer)
    }
}