AVAudioEngine 在连接 AVAudioPlayerNode 输出时抛出异常

AVAudioEngine throws exception when connecting AVAudioPlayerNode to output

我(现在)只想使用 AVAudioEngineAVAudioPlayerNode 播放声音文件。这是我的代码:

//Init engine and player
let audioEngine = AVAudioEngine()
let audioPlayerNode = AVAudioPlayerNode()

//Hook them up
audioEngine.attach(audioPlayerNode)
audioEngine.connect(audioPlayerNode, to: audioEngine.outputNode, format: nil) // < error

执行最后一行时,抛出异常。没有任何内容打印到控制台并继续执行,但是当我设置一个异常断点时,我得到以下 LLDB:

(lldb) po [$arg1 reason]
error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0xffffd593).
The process has been returned to the state before expression evaluation.

这里不能访问什么?我什至还没有加载文件...感谢任何提示。

环境

编辑

这里有一些更多的上下文信息。上面的代码是使用 SpriteKitGameplayKit 构建的 iOS 游戏的一部分。它位于 GKStateMachine 的子类中,在一个名为 playSound 的方法中。此方法在源自我的子类 SKScene 称为 GameScene 的触摸事件过程中被调用。在 touchesBegan 上,调用被委托给所有具有 TouchComponent 且具有相同签名 (touchesBegan) 方法的实体。这些组件将向它们的委托触发一个 touchDown 事件,而委托又是我的 GKStateMachine 的子类,称为 GameStateMachine。如果触摸事件正确w.r.t。游戏规则,我的 GameStateMachinescore 属性 递增。在 score setter 中,如果分数增加,则调用最终方法 playSound。这是我刚才描述的序列图:

下面是一个在 playground 中播放本地文件资源的工作示例:

import AVFoundation
import PlaygroundSupport

// prevent program from exiting immediately
PlaygroundPage.current.needsIndefiniteExecution = true

let fileURL = Bundle.main.url(forResource: "song", withExtension: "mp3")!
let file = try! AVAudioFile(forReading: fileURL)

let audioEngine = AVAudioEngine()
let audioPlayerNode = AVAudioPlayerNode()

audioEngine.attach(audioPlayerNode)
audioEngine.connect(audioPlayerNode, to: audioEngine.outputNode, format: nil)

audioPlayerNode.scheduleFile(file, at: nil, completionHandler: nil)

// need to start the engine before we play
try! audioEngine.start()

audioPlayerNode.play()

这假设 song.mp3 存在于 playground 资源目录中。

显然,抛出的异常是正常。它在我测试过的任何条件和任何环境下都会发生,但不会影响正常功能。

之所以没有播放声音,是因为 AVAudioEngineAVAudioPlayerNode 对象在函数返回后立即被释放,因为它们没有强指针使它们保持活动状态。我通过将这两个对象保留为 properties.

解决了这个问题