AVAudioEngine 在连接 AVAudioPlayerNode 输出时抛出异常
AVAudioEngine throws exception when connecting AVAudioPlayerNode to output
我(现在)只想使用 AVAudioEngine
和 AVAudioPlayerNode
播放声音文件。这是我的代码:
//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.
这里不能访问什么?我什至还没有加载文件...感谢任何提示。
环境
- Xcode 8.2.1
- iPhone 5 运行 在 iOS 10.3.2 (14F89)
编辑
这里有一些更多的上下文信息。上面的代码是使用 SpriteKit
和 GameplayKit
构建的 iOS 游戏的一部分。它位于 GKStateMachine
的子类中,在一个名为 playSound
的方法中。此方法在源自我的子类 SKScene
称为 GameScene
的触摸事件过程中被调用。在 touchesBegan
上,调用被委托给所有具有 TouchComponent
且具有相同签名 (touchesBegan
) 方法的实体。这些组件将向它们的委托触发一个 touchDown
事件,而委托又是我的 GKStateMachine
的子类,称为 GameStateMachine
。如果触摸事件正确w.r.t。游戏规则,我的 GameStateMachine
的 score
属性 递增。在 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 资源目录中。
显然,抛出的异常是正常。它在我测试过的任何条件和任何环境下都会发生,但不会影响正常功能。
之所以没有播放声音,是因为 AVAudioEngine
和 AVAudioPlayerNode
对象在函数返回后立即被释放,因为它们没有强指针使它们保持活动状态。我通过将这两个对象保留为 properties
.
解决了这个问题
我(现在)只想使用 AVAudioEngine
和 AVAudioPlayerNode
播放声音文件。这是我的代码:
//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.
这里不能访问什么?我什至还没有加载文件...感谢任何提示。
环境
- Xcode 8.2.1
- iPhone 5 运行 在 iOS 10.3.2 (14F89)
编辑
这里有一些更多的上下文信息。上面的代码是使用 SpriteKit
和 GameplayKit
构建的 iOS 游戏的一部分。它位于 GKStateMachine
的子类中,在一个名为 playSound
的方法中。此方法在源自我的子类 SKScene
称为 GameScene
的触摸事件过程中被调用。在 touchesBegan
上,调用被委托给所有具有 TouchComponent
且具有相同签名 (touchesBegan
) 方法的实体。这些组件将向它们的委托触发一个 touchDown
事件,而委托又是我的 GKStateMachine
的子类,称为 GameStateMachine
。如果触摸事件正确w.r.t。游戏规则,我的 GameStateMachine
的 score
属性 递增。在 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 资源目录中。
显然,抛出的异常是正常。它在我测试过的任何条件和任何环境下都会发生,但不会影响正常功能。
之所以没有播放声音,是因为 AVAudioEngine
和 AVAudioPlayerNode
对象在函数返回后立即被释放,因为它们没有强指针使它们保持活动状态。我通过将这两个对象保留为 properties
.