Swift: AVAudioPlayer 没有播放,线程可能出错?
Swift: AVAudioPlayer not playing, possible error with threads?
我目前正在开发一款应用,该应用可根据 image/object 的状态播放音频剪辑。
目前我收到此错误代码。
线程 1:EXC_BAD_ACCESS(代码=1,地址=0x48)
我猜当另一个音频剪辑已经在同一线程上播放时,尝试在同一线程上播放另一个音频剪辑可能是一个错误。
但老实说,我不确定,我仍在学习线程和多线程,所以我可能会走到这里。
我在这里错过了什么?如何在不收到此错误消息的情况下播放第二个音频剪辑 (turnSaberOffAudio)?谢谢!
这是我点击按钮时发生的情况。
@objc func lightsaberTapped() {
print("lightsaber open!")
if lightsaberModel.isSaberOn == false {
UIView.animate(withDuration: 0.2, animations: {
self.saberImageHeightConstraint.constant = 530
self.saberImageWidthConstraint.constant = 210
self.mainView.layoutIfNeeded()
self.viewDidLayoutSubviews()
}, completion: nil)
lightsaberModel.turnSaberOnAudio.play()
lightsaberModel.isSaberOn = true
} else {
UIView.animate(withDuration: 0.2, animations: {
self.saberImageHeightConstraint.constant = 1
self.saberImageWidthConstraint.constant = 1
self.mainView.layoutIfNeeded()
self.viewDidLayoutSubviews()
}, completion: nil)
lightsaberModel.turnSaberOffAudio.play()
lightsaberModel.isSaberOn = false
}
}
这是包含必要信息的模型。
class Model {
var turnSaberOnAudio: AVAudioPlayer = AVAudioPlayer()
var turnSaberOffAudio: AVAudioPlayer = AVAudioPlayer()
var whichLightsaber = String()
var isSaberOn = Bool()
func turnSaberOn() {
let turnSaberOnPath = Bundle.main.path(forResource: "SaberOn", ofType: "wav")
do {
turnSaberOnAudio = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: turnSaberOnPath!))
}
catch {
print(error)
}
}
func turnSaberOff() {
let turnSaberOffPath = Bundle.main.path(forResource: "SaberOff", ofType: "mp3")
do {
turnSaberOffAudio = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: turnSaberOffPath!))
}
catch {
print(error)
}
}
}
这是你永远不应该做的事情:
var turnSaberOnAudio: AVAudioPlayer = AVAudioPlayer()
空的初始化器AVAudioPlayer()
创建了一些无用的东西,不仅无用而且有害导致崩溃。
并且将 var 声明为 non-Optional,你无法区分它是否包含有用的东西。
使用您当前的代码,当您调用 play()
时,可能不会调用 turnSaberOn()
或 turnSaberOff()
。
尝试将您的 Model
更改为:
class Model {
var turnSaberOnAudio: AVAudioPlayer? //<- Never use `AVAudioPlayer()`
var turnSaberOffAudio: AVAudioPlayer? //<- Never use `AVAudioPlayer()`
var whichLightsaber: String = ""
var isSaberOn: Bool = false
init() {
let turnSaberOnUrl = Bundle.main.url(forResource: "SaberOn", withExtension: "wav")!
do {
turnSaberOnAudio = try AVAudioPlayer(contentsOf: turnSaberOnUrl)
turnSaberOnAudio!.prepareToPlay()
print("\(turnSaberOnUrl) loaded")
} catch {
print(error)
}
let turnSaberOffUrl = Bundle.main.url(forResource: "SaberOff", withExtension: "mp3")!
do {
turnSaberOffAudio = try AVAudioPlayer(contentsOf: turnSaberOffUrl)
turnSaberOffAudio!.prepareToPlay()
print("\(turnSaberOffUrl) loaded")
} catch {
print(error)
}
//...
}
//...
}
并像这样使用它:
@IBAction func lightSaberTapped(_ sender: Any) {
print("lightsaber open!")
if !lightsaberModel.isSaberOn {
//...
lightsaberModel.turnSaberOnAudio?.play()
lightsaberModel.isSaberOn = true
} else {
//...
lightsaberModel.turnSaberOffAudio?.play()
lightsaberModel.isSaberOn = false
}
}
我目前正在开发一款应用,该应用可根据 image/object 的状态播放音频剪辑。
目前我收到此错误代码。
线程 1:EXC_BAD_ACCESS(代码=1,地址=0x48)
我猜当另一个音频剪辑已经在同一线程上播放时,尝试在同一线程上播放另一个音频剪辑可能是一个错误。
但老实说,我不确定,我仍在学习线程和多线程,所以我可能会走到这里。
我在这里错过了什么?如何在不收到此错误消息的情况下播放第二个音频剪辑 (turnSaberOffAudio)?谢谢!
这是我点击按钮时发生的情况。
@objc func lightsaberTapped() {
print("lightsaber open!")
if lightsaberModel.isSaberOn == false {
UIView.animate(withDuration: 0.2, animations: {
self.saberImageHeightConstraint.constant = 530
self.saberImageWidthConstraint.constant = 210
self.mainView.layoutIfNeeded()
self.viewDidLayoutSubviews()
}, completion: nil)
lightsaberModel.turnSaberOnAudio.play()
lightsaberModel.isSaberOn = true
} else {
UIView.animate(withDuration: 0.2, animations: {
self.saberImageHeightConstraint.constant = 1
self.saberImageWidthConstraint.constant = 1
self.mainView.layoutIfNeeded()
self.viewDidLayoutSubviews()
}, completion: nil)
lightsaberModel.turnSaberOffAudio.play()
lightsaberModel.isSaberOn = false
}
}
这是包含必要信息的模型。
class Model {
var turnSaberOnAudio: AVAudioPlayer = AVAudioPlayer()
var turnSaberOffAudio: AVAudioPlayer = AVAudioPlayer()
var whichLightsaber = String()
var isSaberOn = Bool()
func turnSaberOn() {
let turnSaberOnPath = Bundle.main.path(forResource: "SaberOn", ofType: "wav")
do {
turnSaberOnAudio = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: turnSaberOnPath!))
}
catch {
print(error)
}
}
func turnSaberOff() {
let turnSaberOffPath = Bundle.main.path(forResource: "SaberOff", ofType: "mp3")
do {
turnSaberOffAudio = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: turnSaberOffPath!))
}
catch {
print(error)
}
}
}
这是你永远不应该做的事情:
var turnSaberOnAudio: AVAudioPlayer = AVAudioPlayer()
空的初始化器AVAudioPlayer()
创建了一些无用的东西,不仅无用而且有害导致崩溃。
并且将 var 声明为 non-Optional,你无法区分它是否包含有用的东西。
使用您当前的代码,当您调用 play()
时,可能不会调用 turnSaberOn()
或 turnSaberOff()
。
尝试将您的 Model
更改为:
class Model {
var turnSaberOnAudio: AVAudioPlayer? //<- Never use `AVAudioPlayer()`
var turnSaberOffAudio: AVAudioPlayer? //<- Never use `AVAudioPlayer()`
var whichLightsaber: String = ""
var isSaberOn: Bool = false
init() {
let turnSaberOnUrl = Bundle.main.url(forResource: "SaberOn", withExtension: "wav")!
do {
turnSaberOnAudio = try AVAudioPlayer(contentsOf: turnSaberOnUrl)
turnSaberOnAudio!.prepareToPlay()
print("\(turnSaberOnUrl) loaded")
} catch {
print(error)
}
let turnSaberOffUrl = Bundle.main.url(forResource: "SaberOff", withExtension: "mp3")!
do {
turnSaberOffAudio = try AVAudioPlayer(contentsOf: turnSaberOffUrl)
turnSaberOffAudio!.prepareToPlay()
print("\(turnSaberOffUrl) loaded")
} catch {
print(error)
}
//...
}
//...
}
并像这样使用它:
@IBAction func lightSaberTapped(_ sender: Any) {
print("lightsaber open!")
if !lightsaberModel.isSaberOn {
//...
lightsaberModel.turnSaberOnAudio?.play()
lightsaberModel.isSaberOn = true
} else {
//...
lightsaberModel.turnSaberOffAudio?.play()
lightsaberModel.isSaberOn = false
}
}